feat: TU19 (Dec 2014) Features & Content (#155)

* try to resolve merge conflict

* feat: TU19 (Dec 2014) Features & Content (#32)

* December 2014 files

* Working release build

* Fix compilation issues

* Add sound to Windows64Media

* Add DLC content and force Tutorial DLC

* Revert "Add DLC content and force Tutorial DLC"

This reverts commit 97a4399472.

* Disable broken light packing

* Disable breakpoint during DLC texture map load

Allows DLC loading but the DLC textures are still broken

* Fix post build not working

* ...

* fix vs2022 build

* fix cmake build

---------

Co-authored-by: Loki <lokirautio@gmail.com>
This commit is contained in:
daoge
2026-03-03 03:04:10 +08:00
committed by GitHub
parent 84c31a2331
commit b3feddfef3
2069 changed files with 264842 additions and 139522 deletions

View File

@@ -5,6 +5,7 @@ NetworkPlayerSony::NetworkPlayerSony(SQRNetworkPlayer *qnetPlayer)
{
m_sqrPlayer = qnetPlayer;
m_pSocket = NULL;
m_lastChunkPacketTime = 0;
}
unsigned char NetworkPlayerSony::GetSmallId()
@@ -12,10 +13,10 @@ unsigned char NetworkPlayerSony::GetSmallId()
return m_sqrPlayer->GetSmallId();
}
void NetworkPlayerSony::SendData(INetworkPlayer *player, const void *pvData, int dataSize, bool lowPriority)
void NetworkPlayerSony::SendData(INetworkPlayer *player, const void *pvData, int dataSize, bool lowPriority, bool ack)
{
// TODO - handle priority
m_sqrPlayer->SendData( ((NetworkPlayerSony *)player)->m_sqrPlayer, pvData, dataSize );
m_sqrPlayer->SendData( ((NetworkPlayerSony *)player)->m_sqrPlayer, pvData, dataSize, ack );
}
bool NetworkPlayerSony::IsSameSystem(INetworkPlayer *player)
@@ -23,14 +24,19 @@ bool NetworkPlayerSony::IsSameSystem(INetworkPlayer *player)
return m_sqrPlayer->IsSameSystem(((NetworkPlayerSony *)player)->m_sqrPlayer);
}
int NetworkPlayerSony::GetOutstandingAckCount()
{
return m_sqrPlayer->GetOutstandingAckCount();
}
int NetworkPlayerSony::GetSendQueueSizeBytes( INetworkPlayer *player, bool lowPriority )
{
return 0; // TODO
return m_sqrPlayer->GetSendQueueSizeBytes();
}
int NetworkPlayerSony::GetSendQueueSizeMessages( INetworkPlayer *player, bool lowPriority )
{
return 0; // TODO
return m_sqrPlayer->GetSendQueueSizeMessages();
}
int NetworkPlayerSony::GetCurrentRtt()
@@ -112,3 +118,20 @@ void NetworkPlayerSony::SetUID(PlayerUID UID)
{
m_sqrPlayer->SetUID(UID);
}
void NetworkPlayerSony::SentChunkPacket()
{
m_lastChunkPacketTime = System::currentTimeMillis();
}
int NetworkPlayerSony::GetTimeSinceLastChunkPacket_ms()
{
// If we haven't ever sent a packet, return maximum
if( m_lastChunkPacketTime == 0 )
{
return INT_MAX;
}
__int64 currentTime = System::currentTimeMillis();
return (int)( currentTime - m_lastChunkPacketTime );
}

View File

@@ -11,8 +11,9 @@ public:
// Common player interface
NetworkPlayerSony(SQRNetworkPlayer *sqrPlayer);
virtual unsigned char GetSmallId();
virtual void SendData(INetworkPlayer *player, const void *pvData, int dataSize, bool lowPriority);
virtual void SendData(INetworkPlayer *player, const void *pvData, int dataSize, bool lowPriority, bool ack);
virtual bool IsSameSystem(INetworkPlayer *player);
virtual int GetOutstandingAckCount();
virtual int GetSendQueueSizeBytes( INetworkPlayer *player, bool lowPriority );
virtual int GetSendQueueSizeMessages( INetworkPlayer *player, bool lowPriority );
virtual int GetCurrentRtt();
@@ -33,7 +34,10 @@ public:
void SetUID(PlayerUID UID);
virtual void SentChunkPacket();
virtual int GetTimeSinceLastChunkPacket_ms();
private:
SQRNetworkPlayer *m_sqrPlayer;
Socket *m_pSocket;
__int64 m_lastChunkPacketTime;
};

View File

@@ -54,10 +54,8 @@ void CPlatformNetworkManagerSony::HandleStateChange(SQRNetworkManager::eSQRNetwo
else if( newState == SQRNetworkManager::SNM_STATE_JOINING )
{
// 4J Stu - We may be accepting an invite from the DLC menu, so hide the icon
#ifdef __ORBIS__
sceNpCommerceHidePsStoreIcon();
#elif defined __PSVITA__
sceNpCommerce2HidePsStoreIcon();
#if defined __ORBIS__ || defined __PSVITA__
app.GetCommerce()->HidePsStoreIcon();
#endif
m_bLeavingGame = false;
m_bLeaveGameOnTick = false;
@@ -459,16 +457,16 @@ int CPlatformNetworkManagerSony::CorrectErrorIDS(int IDS)
// Determine if we'd prefer to present errors as a signing out issue, rather than a network issue, based on whether we have a network connection at all or not
bool preferSignoutError = false;
int state;
#ifdef __PS3__
#if defined __PSVITA__ // MGH - to fix devtrack #6258
if(!ProfileManager.IsSignedInPSN(ProfileManager.GetPrimaryPad()))
preferSignoutError = true;
#elif defined __ORBIS__
if(!ProfileManager.isSignedInPSN(ProfileManager.GetPrimaryPad()))
preferSignoutError = true;
#elif defined __PS3__
int ret = cellNetCtlGetState( &state );
int IPObtainedState = CELL_NET_CTL_STATE_IPObtained;
#elif defined __ORBIS__
int ret = sceNetCtlGetState( &state );
int IPObtainedState = SCE_NET_CTL_STATE_IPOBTAINED;
#elif defined __PSVITA__
int ret = sceNetCtlInetGetState( &state );
int IPObtainedState = SCE_NET_CTL_STATE_IPOBTAINED;
#endif
if( ret == 0 )
{
if( state == IPObtainedState )
@@ -476,6 +474,7 @@ int CPlatformNetworkManagerSony::CorrectErrorIDS(int IDS)
preferSignoutError = true;
}
}
#endif
#ifdef __PSVITA__
// If we're in ad-hoc mode this problem definitely wasn't PSN related
@@ -1446,7 +1445,8 @@ void CPlatformNetworkManagerSony::startAdhocMatching( )
bool CPlatformNetworkManagerSony::checkValidInviteData(const INVITE_INFO* pInviteInfo)
{
if(((SQRNetworkManager_Vita*)m_pSQRNet_Vita)->GetHostUID() == pInviteInfo->hostPlayerUID)
SQRNetworkManager_Vita* pSQR = (SQRNetworkManager_Vita*)m_pSQRNet_Vita;
if(pSQR->IsOnlineGame() && !pSQR->IsHost()&& (pSQR->GetHostUID() == pInviteInfo->hostPlayerUID))
{
// we're trying to join a game we're already in, so we just ignore this
return false;

View File

@@ -8,3 +8,76 @@ void SQRNetworkManager::SafeToRespondToGameBootInvite()
{
s_safeToRespondToGameBootInvite = true;
}
int SQRNetworkManager::GetSendQueueSizeBytes()
{
int queueSize = 0;
int playerCount = GetPlayerCount();
for(int i = 0; i < playerCount; ++i)
{
SQRNetworkPlayer *player = GetPlayerByIndex( i );
if( player != NULL )
{
queueSize += player->GetTotalSendQueueBytes();
}
}
return queueSize;
}
int SQRNetworkManager::GetSendQueueSizeMessages()
{
int queueSize = 0;
int playerCount = GetPlayerCount();
for(int i = 0; i < playerCount; ++i)
{
SQRNetworkPlayer *player = GetPlayerByIndex( i );
if( player != NULL )
{
queueSize += player->GetTotalSendQueueMessages();
}
}
return queueSize;
}
int SQRNetworkManager::GetOutstandingAckCount(SQRNetworkPlayer *pSQRPlayer)
{
int ackCount = 0;
int playerCount = GetPlayerCount();
for(int i = 0; i < playerCount; ++i)
{
SQRNetworkPlayer *pSQRPlayer2 = GetPlayerByIndex( i );
if( pSQRPlayer2 )
{
if( ( pSQRPlayer == pSQRPlayer2 ) || (pSQRPlayer->IsSameSystem(pSQRPlayer2) ) )
{
ackCount += pSQRPlayer2->m_acksOutstanding;
}
}
}
return ackCount;
}
void SQRNetworkManager::RequestWriteAck(int smallId)
{
EnterCriticalSection(&m_csAckQueue);
m_queuedAckRequests.push(smallId);
LeaveCriticalSection(&m_csAckQueue);
}
void SQRNetworkManager::TickWriteAcks()
{
EnterCriticalSection(&m_csAckQueue);
while(m_queuedAckRequests.size() > 0)
{
int smallId = m_queuedAckRequests.front();
m_queuedAckRequests.pop();
SQRNetworkPlayer *player = GetPlayerBySmallId(smallId);
if( player )
{
LeaveCriticalSection(&m_csAckQueue);
player->WriteAck();
EnterCriticalSection(&m_csAckQueue);
}
}
LeaveCriticalSection(&m_csAckQueue);
}

View File

@@ -11,6 +11,9 @@
#include <queue>
#include <unordered_map>
#if defined __PSVITA__
#include "..\..\Minecraft.Client\PSVita\4JLibs\inc\4J_Profile.h"
#endif
class SQRNetworkPlayer;
class ISQRNetworkManagerListener;
@@ -30,7 +33,9 @@ public:
protected:
friend class SQRNetworkPlayer;
friend class SonyVoiceChat;
#ifdef __PSVITA__
friend class HelloSyncInfo;
#endif
static const int MAX_FRIENDS = 100;
#ifdef __PS3__
@@ -231,6 +236,8 @@ protected:
std::queue<StateChangeInfo> m_stateChangeQueue;
CRITICAL_SECTION m_csStateChangeQueue;
CRITICAL_SECTION m_csMatching;
CRITICAL_SECTION m_csAckQueue;
std::queue<int> m_queuedAckRequests;
typedef enum
{
@@ -295,6 +302,13 @@ public:
static void SafeToRespondToGameBootInvite();
int GetOutstandingAckCount(SQRNetworkPlayer *pSonyPlayer);
int GetSendQueueSizeBytes();
int GetSendQueueSizeMessages();
void RequestWriteAck(int smallId);
void TickWriteAcks();
};

View File

@@ -16,6 +16,15 @@
#endif
//#define PRINT_ACK_STATS
#ifdef __PS3__
static const int sc_wouldBlockFlag = CELL_RUDP_ERROR_WOULDBLOCK;
#else // __ORBIS__
static const int sc_wouldBlockFlag = SCE_RUDP_ERROR_WOULDBLOCK;
#endif
static const bool sc_verbose = false;
@@ -84,6 +93,8 @@ SQRNetworkPlayer::SQRNetworkPlayer(SQRNetworkManager *manager, eSQRNetworkPlayer
m_host = onHost;
m_manager = manager;
m_customData = 0;
m_acksOutstanding = 0;
m_totalBytesInSendQueue = 0;
if( pUID )
{
memcpy(&m_ISD.m_UID,pUID,sizeof(PlayerUID));
@@ -102,6 +113,7 @@ SQRNetworkPlayer::SQRNetworkPlayer(SQRNetworkManager *manager, eSQRNetworkPlayer
}
SetNameFromUID();
InitializeCriticalSection(&m_csQueue);
InitializeCriticalSection(&m_csAcks);
#ifdef __ORBIS__
if(IsLocal())
{
@@ -109,6 +121,14 @@ SQRNetworkPlayer::SQRNetworkPlayer(SQRNetworkManager *manager, eSQRNetworkPlayer
}
#endif
#ifndef _CONTENT_PACKAGE
m_minAckTime = INT_MAX;
m_maxAckTime = 0;
m_totalAcks = 0;
m_totalAckTime = 0;
m_averageAckTime = 0;
#endif
}
SQRNetworkPlayer::~SQRNetworkPlayer()
@@ -190,13 +210,8 @@ bool SQRNetworkPlayer::HasSmallIdConfirmed()
// 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) );
SendInternal(&m_ISD, sizeof(InitSendData), e_flag_AckNotRequested);
// 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");
@@ -205,8 +220,9 @@ void SQRNetworkPlayer::ConfirmReady()
// 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 )
void SQRNetworkPlayer::SendData( SQRNetworkPlayer *pPlayerTarget, const void *data, unsigned int dataSize, bool ack )
{
AckFlags ackFlags = ack ? e_flag_AckRequested : e_flag_AckNotRequested;
// 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 )
@@ -224,7 +240,7 @@ void SQRNetworkPlayer::SendData( SQRNetworkPlayer *pPlayerTarget, const void *da
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);
pPlayerTarget->SendInternal(data,dataSize, ackFlags);
}
else
{
@@ -237,7 +253,7 @@ void SQRNetworkPlayer::SendData( SQRNetworkPlayer *pPlayerTarget, const void *da
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);
SendInternal(data, dataSize, ackFlags);
}
else
{
@@ -250,15 +266,30 @@ void SQRNetworkPlayer::SendData( SQRNetworkPlayer *pPlayerTarget, const void *da
// 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)
void SQRNetworkPlayer::SendInternal(const void *data, unsigned int dataSize, AckFlags ackFlags)
{
EnterCriticalSection(&m_csQueue);
bool bOutstandingPackets = (m_sendQueue.size() > 0); // check if there are still packets in the queue, we won't be calling SendMoreInternal here if there are
QueuedSendBlock sendBlock;
unsigned char *dataCurrent = (unsigned char *)data;
unsigned int dataRemaining = dataSize;
if(ackFlags == e_flag_AckReturning)
{
// no data, just the flag
assert(dataSize == 0);
assert(data == NULL);
int dataSize = dataRemaining;
if( dataSize > SNP_MAX_PAYLOAD ) dataSize = SNP_MAX_PAYLOAD;
sendBlock.start = NULL;
sendBlock.end = NULL;
sendBlock.current = NULL;
sendBlock.ack = ackFlags;
m_sendQueue.push(sendBlock);
}
else
{
while( dataRemaining )
{
int dataSize = dataRemaining;
@@ -266,19 +297,203 @@ void SQRNetworkPlayer::SendInternal(const void *data, unsigned int dataSize)
sendBlock.start = new unsigned char [dataSize];
sendBlock.end = sendBlock.start + dataSize;
sendBlock.current = sendBlock.start;
sendBlock.ack = ackFlags;
memcpy( sendBlock.start, dataCurrent, dataSize);
m_sendQueue.push(sendBlock);
dataRemaining -= dataSize;
dataCurrent += dataSize;
}
// Now try and send as much as we can
SendMoreInternal();
}
m_totalBytesInSendQueue += dataSize;
// if the queue had something in it already, then the UDP callback will fire and call SendMoreInternal
// so we don't call it here, to avoid a deadlock
if(!bOutstandingPackets)
{
// Now try and send as much as we can
SendMoreInternal();
}
LeaveCriticalSection(&m_csQueue);
}
int SQRNetworkPlayer::WriteDataPacket(const void* data, int dataSize, AckFlags ackFlags)
{
DataPacketHeader header(dataSize, ackFlags);
int headerSize = sizeof(header);
int packetSize = dataSize+headerSize;
unsigned char* packetData = new unsigned char[packetSize];
*((DataPacketHeader*)packetData) = header;
memcpy(&packetData[headerSize], data, dataSize);
#ifndef _CONTENT_PACKAGE
if(ackFlags == e_flag_AckRequested)
m_ackStats.push_back(System::currentTimeMillis());
#endif
#ifdef __PS3__
int ret = cellRudpWrite( m_rudpCtx, packetData, packetSize, 0);//CELL_RUDP_MSG_LATENCY_CRITICAL );
#else // __ORBIS__ && __PSVITA__
int ret = sceRudpWrite( m_rudpCtx, packetData, packetSize, 0);//SCE_RUDP_MSG_LATENCY_CRITICAL );
#endif
if(ret == sc_wouldBlockFlag)
{
// nothing was sent!
}
else
{
assert(ret==packetSize || ret > headerSize); // we must make sure we've sent the entire packet or the header and some data at least
ret -= headerSize;
if(ackFlags == e_flag_AckRequested)
{
EnterCriticalSection(&m_csAcks);
m_acksOutstanding++;
LeaveCriticalSection(&m_csAcks);
}
}
delete packetData;
return ret;
}
int SQRNetworkPlayer::GetPacketDataSize()
{
unsigned int ackFlag;
int headerSize = sizeof(ackFlag);
#ifdef __PS3__
unsigned int packetSize = cellRudpGetSizeReadable(m_rudpCtx);
#else
unsigned int packetSize = sceRudpGetSizeReadable(m_rudpCtx);
#endif
if(packetSize == 0)
return 0;
unsigned int dataSize = packetSize - headerSize;
assert(dataSize >= 0);
if(dataSize == 0)
{
// header only, must just be an ack returning
ReadAck();
}
return dataSize;
}
int SQRNetworkPlayer::ReadDataPacket(void* data, int dataSize)
{
int headerSize = sizeof(DataPacketHeader);
int packetSize = dataSize+headerSize;
unsigned char* packetData = new unsigned char[packetSize];
#ifdef __PS3__
int bytesRead = cellRudpRead( m_rudpCtx, packetData, packetSize, 0, NULL );
#else // __ORBIS__ && __PSVITA__
int bytesRead = sceRudpRead( m_rudpCtx, packetData, packetSize, 0, NULL );
#endif
if(bytesRead == sc_wouldBlockFlag)
{
delete packetData;
return 0;
}
// check the header, and see if we need to send back an ack
DataPacketHeader header = *((DataPacketHeader*)packetData);
if(header.GetAckFlags() == e_flag_AckRequested)
{
// Don't send the ack back directly from here, as this is called from a rudp event callback, and we end up in a thread lock situation between the lock librudp uses
// internally (which is locked already here since we are being called in the event handler), and our own lock that we do for processing our write queue
m_manager->RequestWriteAck(GetSmallId());
}
else
{
assert(header.GetAckFlags() == e_flag_AckNotRequested);
}
if(bytesRead > 0)
{
bytesRead -= headerSize;
memcpy(data, &packetData[headerSize], bytesRead);
}
assert(header.GetDataSize() == bytesRead);
delete packetData;
return bytesRead;
}
void SQRNetworkPlayer::ReadAck()
{
DataPacketHeader header;
#ifdef __PS3__
int bytesRead = cellRudpRead( m_rudpCtx, &header, sizeof(header), 0, NULL );
#else // __ORBIS__ && __PSVITA__
int bytesRead = sceRudpRead( m_rudpCtx, &header, sizeof(header), 0, NULL );
#endif
if(bytesRead == sc_wouldBlockFlag)
{
return;
}
assert(header.GetAckFlags() == e_flag_AckReturning);
EnterCriticalSection(&m_csAcks);
m_acksOutstanding--;
assert(m_acksOutstanding >=0);
LeaveCriticalSection(&m_csAcks);
#ifndef _CONTENT_PACKAGE
#ifdef PRINT_ACK_STATS
__int64 timeTaken = System::currentTimeMillis() - m_ackStats[0];
if(timeTaken < m_minAckTime)
m_minAckTime = timeTaken;
if(timeTaken > m_maxAckTime)
m_maxAckTime = timeTaken;
m_totalAcks++;
m_totalAckTime += timeTaken;
m_averageAckTime = m_totalAckTime / m_totalAcks;
app.DebugPrintf("RUDP ctx : %d : Time taken for ack - %4d ms : min - %4d : max %4d : avg %4d\n", m_rudpCtx, timeTaken, m_minAckTime, m_maxAckTime, m_averageAckTime);
m_ackStats.erase(m_ackStats.begin());
#endif
#endif
}
void SQRNetworkPlayer::WriteAck()
{
SendInternal(NULL, 0, e_flag_AckReturning);
}
int SQRNetworkPlayer::GetOutstandingAckCount()
{
return m_manager->GetOutstandingAckCount(this);
}
int SQRNetworkPlayer::GetTotalOutstandingAckCount()
{
return m_acksOutstanding;
}
int SQRNetworkPlayer::GetTotalSendQueueBytes()
{
return m_totalBytesInSendQueue;
}
int SQRNetworkPlayer::GetTotalSendQueueMessages()
{
CriticalSectionScopeLock lock(&m_csQueue);
return m_sendQueue.size();
}
int SQRNetworkPlayer::GetSendQueueSizeBytes()
{
return m_manager->GetSendQueueSizeBytes();
}
int SQRNetworkPlayer::GetSendQueueSizeMessages()
{
return m_manager->GetSendQueueSizeMessages();
}
// 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,
@@ -287,6 +502,8 @@ void SQRNetworkPlayer::SendInternal(const void *data, unsigned int dataSize)
void SQRNetworkPlayer::SendMoreInternal()
{
EnterCriticalSection(&m_csQueue);
assert(m_sendQueue.size() > 0); // this should never be called with an empty queue.
bool keepSending;
do
{
@@ -296,17 +513,12 @@ void SQRNetworkPlayer::SendMoreInternal()
// 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;
int ret = WriteDataPacket(data, dataSize, m_sendQueue.front().ack);
#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
m_totalBytesInSendQueue -= ret;
delete [] m_sendQueue.front().start;
m_sendQueue.pop();
if( m_sendQueue.size() )
@@ -314,15 +526,15 @@ void SQRNetworkPlayer::SendMoreInternal()
keepSending = true;
}
}
else if( ( ret >= 0 ) || ( ret == wouldBlockFlag ) )
else if( ( ret >= 0 ) || ( ret == sc_wouldBlockFlag ) )
{
// Things left to send - adjust this element in the queue
int remainingBytes;
if( ret >= 0 )
{
// Only ret bytes sent so far
m_totalBytesInSendQueue -= ret;
remainingBytes = dataSize - ret;
assert(remainingBytes > 0 );
}

View File

@@ -48,12 +48,41 @@ class SQRNetworkPlayer
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;
enum AckFlags
{
e_flag_AckUnknown,
e_flag_AckNotRequested,
e_flag_AckRequested,
e_flag_AckReturning
};
class DataPacketHeader
{
unsigned short m_dataSize;
unsigned short m_ackFlags;
public:
DataPacketHeader() : m_dataSize(0), m_ackFlags(e_flag_AckUnknown) {}
DataPacketHeader(int dataSize, AckFlags ackFlags) : m_dataSize(dataSize), m_ackFlags(ackFlags) { }
AckFlags GetAckFlags() { return (AckFlags)m_ackFlags;}
int GetDataSize() { return m_dataSize; }
};
#ifndef _CONTENT_PACKAGE
std::vector<__int64> m_ackStats;
int m_minAckTime;
int m_maxAckTime;
int m_totalAcks;
__int64 m_totalAckTime;
int m_averageAckTime;
#endif
class QueuedSendBlock
{
public:
unsigned char *start;
unsigned char *end;
unsigned char *current;
AckFlags ack;
};
class InitSendData
@@ -75,11 +104,26 @@ class SQRNetworkPlayer
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 SendData( SQRNetworkPlayer *pPlayerTarget, const void *data, unsigned int dataSize, bool ack );
void ConfirmReady();
void SendInternal(const void *data, unsigned int dataSize);
void SendInternal(const void *data, unsigned int dataSize, AckFlags ackFlags);
void SendMoreInternal();
int GetPacketDataSize();
int ReadDataPacket(void* data, int dataSize);
int WriteDataPacket(const void* data, int dataSize, AckFlags ackFlags);
void ReadAck();
void WriteAck();
int GetOutstandingAckCount();
int GetSendQueueSizeBytes();
int GetSendQueueSizeMessages();
int GetTotalOutstandingAckCount();
int GetTotalSendQueueBytes();
int GetTotalSendQueueMessages();
#ifdef __PSVITA__
void SendInternal_VitaAdhoc(const void *data, unsigned int dataSize, EAdhocDataTag tag = e_dataTag_Normal);
void SendMoreInternal_VitaAdhoc();
@@ -99,5 +143,9 @@ class SQRNetworkPlayer
wchar_t m_name[21];
uintptr_t m_customData;
CRITICAL_SECTION m_csQueue;
CRITICAL_SECTION m_csAcks;
std::queue<QueuedSendBlock> m_sendQueue;
int m_totalBytesInSendQueue;
int m_acksOutstanding;
};

View File

@@ -170,4 +170,8 @@ public:
virtual void CheckForTrialUpgradeKey() = 0;
virtual bool LicenseChecked() = 0;
#if defined __ORBIS__ || defined __PSVITA__
virtual void ShowPsStoreIcon() = 0;
virtual void HidePsStoreIcon() = 0;
#endif
};

View File

@@ -36,6 +36,37 @@ static SceRemoteStorageStatus statParams;
void SonyRemoteStorage::SetRetrievedDescData()
{
DescriptionData* pDescDataTest = (DescriptionData*)m_remoteFileInfo->fileDescription;
ESavePlatform testPlatform = (ESavePlatform)MAKE_FOURCC(pDescDataTest->m_platform[0], pDescDataTest->m_platform[1], pDescDataTest->m_platform[2], pDescDataTest->m_platform[3]);
if(testPlatform == SAVE_FILE_PLATFORM_NONE)
{
// new version of the descData
DescriptionData_V2* pDescData2 = (DescriptionData_V2*)m_remoteFileInfo->fileDescription;
m_retrievedDescData.m_descDataVersion = GetU32FromHexBytes(pDescData2->m_descDataVersion);
m_retrievedDescData.m_savePlatform = (ESavePlatform)MAKE_FOURCC(pDescData2->m_platform[0], pDescData2->m_platform[1], pDescData2->m_platform[2], pDescData2->m_platform[3]);
m_retrievedDescData.m_seed = GetU64FromHexBytes(pDescData2->m_seed);
m_retrievedDescData.m_hostOptions = GetU32FromHexBytes(pDescData2->m_hostOptions);
m_retrievedDescData.m_texturePack = GetU32FromHexBytes(pDescData2->m_texturePack);
m_retrievedDescData.m_saveVersion = GetU32FromHexBytes(pDescData2->m_saveVersion);
memcpy(m_retrievedDescData.m_saveNameUTF8, pDescData2->m_saveNameUTF8, sizeof(pDescData2->m_saveNameUTF8));
assert(m_retrievedDescData.m_descDataVersion > 1 && m_retrievedDescData.m_descDataVersion <= sc_CurrentDescDataVersion);
}
else
{
// old version,copy the data across to the new version
DescriptionData* pDescData = (DescriptionData*)m_remoteFileInfo->fileDescription;
m_retrievedDescData.m_descDataVersion = 1;
m_retrievedDescData.m_savePlatform = (ESavePlatform)MAKE_FOURCC(pDescData->m_platform[0], pDescData->m_platform[1], pDescData->m_platform[2], pDescData->m_platform[3]);
m_retrievedDescData.m_seed = GetU64FromHexBytes(pDescData->m_seed);
m_retrievedDescData.m_hostOptions = GetU32FromHexBytes(pDescData->m_hostOptions);
m_retrievedDescData.m_texturePack = GetU32FromHexBytes(pDescData->m_texturePack);
m_retrievedDescData.m_saveVersion = SAVE_FILE_VERSION_COMPRESSED_CHUNK_STORAGE; // the last save version before we added it to this data
memcpy(m_retrievedDescData.m_saveNameUTF8, pDescData->m_saveNameUTF8, sizeof(pDescData->m_saveNameUTF8));
}
}
@@ -51,8 +82,9 @@ void getSaveInfoReturnCallback(LPVOID lpParam, SonyRemoteStorage::Status s, int
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];
pRemoteStorage->SetRetrievedDescData();
pRemoteStorage->m_getInfoStatus = SonyRemoteStorage::e_infoFound;
}
}
}
@@ -104,7 +136,7 @@ void SonyRemoteStorage::getSaveInfo()
bool SonyRemoteStorage::getSaveData( const char* localDirname, CallbackFunc cb, LPVOID lpParam )
{
m_startTime = System::currentTimeMillis();
m_dataProgress = 0;
m_dataProgress = -1;
return getData(sc_remoteSaveFilename, localDirname, cb, lpParam);
}
@@ -131,7 +163,9 @@ bool SonyRemoteStorage::setSaveData(PSAVE_INFO info, CallbackFunc cb, void* lpPa
m_setDataStatus = e_settingData;
m_initCallbackFunc = cb;
m_initCallbackParam = lpParam;
m_dataProgress = 0;
m_dataProgress = -1;
m_uploadSaveSize = 0;
m_startTime = System::currentTimeMillis();
bool bOK = init(setSaveDataInitCallback, this);
if(!bOK)
m_setDataStatus = e_settingDataFailed;
@@ -148,16 +182,14 @@ const char* SonyRemoteStorage::getSaveNameUTF8()
{
if(m_getInfoStatus != e_infoFound)
return NULL;
DescriptionData* pDescData = (DescriptionData*)m_remoteFileInfo->fileDescription;
return pDescData->m_saveNameUTF8;
return m_retrievedDescData.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]);
return m_retrievedDescData.m_savePlatform;
}
@@ -165,51 +197,23 @@ __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;
return m_retrievedDescData.m_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;
return m_retrievedDescData.m_hostOptions;
}
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;
return m_retrievedDescData.m_texturePack;
}
const char* SonyRemoteStorage::getRemoteSaveFilename()
@@ -292,14 +296,41 @@ bool SonyRemoteStorage::saveIsAvailable()
#endif
}
bool SonyRemoteStorage::saveVersionSupported()
{
return (m_retrievedDescData.m_saveVersion <= SAVE_FILE_VERSION_NUMBER);
}
int SonyRemoteStorage::getDataProgress()
{
if(m_dataProgress < 0)
return 0;
int chunkSize = 1024*1024; // 1mb chunks when downloading
int totalSize = getSaveFilesize();
int transferRatePerSec = 300*1024; // a pessimistic download transfer rate
if(getStatus() == e_setDataInProgress)
{
chunkSize = 5 * 1024 * 1024; // 5mb chunks when uploading
totalSize = m_uploadSaveSize;
transferRatePerSec = 20*1024; // a pessimistic upload transfer rate
}
int sizeTransferred = (totalSize * m_dataProgress) / 100;
int nextChunk = ((sizeTransferred + chunkSize) * 100) / totalSize;
__int64 time = System::currentTimeMillis();
int elapsedSecs = (time - m_startTime) / 1000;
int progVal = m_dataProgress + (elapsedSecs/3);
if(progVal > 95)
float estimatedTransfered = float(elapsedSecs * transferRatePerSec);
int progVal = m_dataProgress + (estimatedTransfered / float(totalSize)) * 100;
if(progVal > nextChunk)
return nextChunk;
if(progVal > 99)
{
return m_dataProgress;
if(m_dataProgress > 99)
return m_dataProgress;
return 99;
}
return progVal;
}
@@ -338,3 +369,139 @@ void SonyRemoteStorage::waitForStorageManagerIdle()
storageState = StorageManager.GetSaveState();
}
}
void SonyRemoteStorage::GetDescriptionData(char* descData)
{
switch(sc_CurrentDescDataVersion)
{
case 1:
{
DescriptionData descData_V1;
GetDescriptionData(descData_V1);
memcpy(descData, &descData_V1, sizeof(descData_V1));
}
break;
case 2:
{
DescriptionData_V2 descData_V2;
GetDescriptionData(descData_V2);
memcpy(descData, &descData_V2, sizeof(descData_V2));
}
break;
default:
assert(0);
break;
}
}
void SonyRemoteStorage::GetDescriptionData( DescriptionData& descData)
{
ZeroMemory(&descData, sizeof(DescriptionData));
descData.m_platform[0] = SAVE_FILE_PLATFORM_LOCAL & 0xff;
descData.m_platform[1] = (SAVE_FILE_PLATFORM_LOCAL >> 8) & 0xff;
descData.m_platform[2] = (SAVE_FILE_PLATFORM_LOCAL >> 16) & 0xff;
descData.m_platform[3] = (SAVE_FILE_PLATFORM_LOCAL >> 24)& 0xff;
if(m_thumbnailData)
{
unsigned int uiHostOptions;
bool bHostOptionsRead;
DWORD uiTexturePack;
char seed[22];
app.GetImageTextData(m_thumbnailData, m_thumbnailDataSize,(unsigned char *)seed, uiHostOptions, bHostOptionsRead, uiTexturePack);
__int64 iSeed = strtoll(seed,NULL,10);
SetU64HexBytes(descData.m_seed, iSeed);
// Save the host options that this world was last played with
SetU32HexBytes(descData.m_hostOptions, uiHostOptions);
// Save the texture pack id
SetU32HexBytes(descData.m_texturePack, uiTexturePack);
}
memcpy(descData.m_saveNameUTF8, m_saveFileDesc, strlen(m_saveFileDesc));
}
void SonyRemoteStorage::GetDescriptionData( DescriptionData_V2& descData)
{
ZeroMemory(&descData, sizeof(DescriptionData_V2));
descData.m_platformNone[0] = SAVE_FILE_PLATFORM_NONE & 0xff;
descData.m_platformNone[1] = (SAVE_FILE_PLATFORM_NONE >> 8) & 0xff;
descData.m_platformNone[2] = (SAVE_FILE_PLATFORM_NONE >> 16) & 0xff;
descData.m_platformNone[3] = (SAVE_FILE_PLATFORM_NONE >> 24)& 0xff;
// Save descData version
char descDataVersion[9];
sprintf(descDataVersion,"%08x",sc_CurrentDescDataVersion);
memcpy(descData.m_descDataVersion,descDataVersion,8); // Don't copy null
descData.m_platform[0] = SAVE_FILE_PLATFORM_LOCAL & 0xff;
descData.m_platform[1] = (SAVE_FILE_PLATFORM_LOCAL >> 8) & 0xff;
descData.m_platform[2] = (SAVE_FILE_PLATFORM_LOCAL >> 16) & 0xff;
descData.m_platform[3] = (SAVE_FILE_PLATFORM_LOCAL >> 24)& 0xff;
if(m_thumbnailData)
{
unsigned int uiHostOptions;
bool bHostOptionsRead;
DWORD uiTexturePack;
char seed[22];
app.GetImageTextData(m_thumbnailData, m_thumbnailDataSize,(unsigned char *)seed, uiHostOptions, bHostOptionsRead, uiTexturePack);
__int64 iSeed = strtoll(seed,NULL,10);
SetU64HexBytes(descData.m_seed, iSeed);
// Save the host options that this world was last played with
SetU32HexBytes(descData.m_hostOptions, uiHostOptions);
// Save the texture pack id
SetU32HexBytes(descData.m_texturePack, uiTexturePack);
// Save the savefile version
SetU32HexBytes(descData.m_saveVersion, SAVE_FILE_VERSION_NUMBER);
// clear out the future data with underscores
memset(descData.m_futureData, '_', sizeof(descData.m_futureData));
}
memcpy(descData.m_saveNameUTF8, m_saveFileDesc, strlen(m_saveFileDesc));
}
uint32_t SonyRemoteStorage::GetU32FromHexBytes(char* hexBytes)
{
char hexString[9];
ZeroMemory(hexString,9);
memcpy(hexString, hexBytes,8);
uint32_t u32Val = 0;
std::stringstream ss;
ss << hexString;
ss >> std::hex >> u32Val;
return u32Val;
}
uint64_t SonyRemoteStorage::GetU64FromHexBytes(char* hexBytes)
{
char hexString[17];
ZeroMemory(hexString,17);
memcpy(hexString, hexBytes,16);
uint64_t u64Val = 0;
std::stringstream ss;
ss << hexString;
ss >> std::hex >> u64Val;
return u64Val;
}
void SonyRemoteStorage::SetU32HexBytes(char* hexBytes, uint32_t u32)
{
char hexString[9];
sprintf(hexString,"%08x",u32);
memcpy(hexBytes,hexString,8); // Don't copy null
}
void SonyRemoteStorage::SetU64HexBytes(char* hexBytes, uint64_t u64)
{
char hexString[17];
sprintf(hexString,"%016llx",u64);
memcpy(hexBytes,hexString,16); // Don't copy null
}

View File

@@ -40,6 +40,7 @@ public:
PSAVE_INFO m_setSaveDataInfo;
SceRemoteStorageData* m_remoteFileInfo;
char m_saveFileDesc[128];
class DescriptionData
{
@@ -52,6 +53,47 @@ public:
char m_saveNameUTF8[128];
};
class DescriptionData_V2
{
// this stuff is read from a JSON query, so it all has to be text based, max 256 bytes
public:
char m_platformNone[4]; // set to no platform, to indicate we're using the newer version of the data
char m_descDataVersion[8]; // 4 bytes as hex - version number will be 2 in this case
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_saveVersion[8]; // 4 bytes as hex
char m_futureData[64]; // some space for future data in case we need to expand this at all
char m_saveNameUTF8[128];
};
class DescriptionDataParsed
{
public:
int m_descDataVersion;
ESavePlatform m_savePlatform;
__int64 m_seed;
uint32_t m_hostOptions;
uint32_t m_texturePack;
uint32_t m_saveVersion;
char m_saveNameUTF8[128];
};
static const int sc_CurrentDescDataVersion = 2;
void GetDescriptionData(char* descData);
void GetDescriptionData(DescriptionData& descData);
void GetDescriptionData(DescriptionData_V2& descData);
uint32_t GetU32FromHexBytes(char* hexBytes);
uint64_t GetU64FromHexBytes(char* hexBytes);
void SetU32HexBytes(char* hexBytes, uint32_t u32);
void SetU64HexBytes(char* hexBytes, uint64_t u64);
DescriptionDataParsed m_retrievedDescData;
void SetRetrievedDescData();
CallbackFunc m_callbackFunc;
void* m_callbackParam;
@@ -62,6 +104,7 @@ public:
void getSaveInfo();
bool waitingForSaveInfo() { return (m_getInfoStatus == e_gettingInfo); }
bool saveIsAvailable();
bool saveVersionSupported();
int getSaveFilesize();
bool getSaveData(const char* localDirname, CallbackFunc cb, LPVOID lpParam);
@@ -115,6 +158,6 @@ protected:
bool m_bAborting;
bool m_bTransferStarted;
int m_uploadSaveSize;
};