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:
@@ -6,6 +6,7 @@
|
||||
#include "..\..\..\Minecraft.World\ThreadName.h"
|
||||
#include "..\..\..\Minecraft.World\Entity.h"
|
||||
#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.h"
|
||||
#include "..\..\..\Minecraft.World\FireworksRecipe.h"
|
||||
#include "..\..\ClientConnection.h"
|
||||
#include "..\..\Minecraft.h"
|
||||
#include "..\..\User.h"
|
||||
@@ -30,7 +31,7 @@
|
||||
|
||||
#ifdef _XBOX
|
||||
#include "Common\XUI\XUI_PauseMenu.h"
|
||||
#elif !(defined __PSVITA__)
|
||||
#else
|
||||
#include "Common\UI\UI.h"
|
||||
#include "Common\UI\UIScene_PauseMenu.h"
|
||||
#include "..\..\Xbox\Network\NetworkPlayerXbox.h"
|
||||
@@ -204,7 +205,79 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame
|
||||
}
|
||||
else
|
||||
{
|
||||
param->seed = seed = app.getLevelGenerationOptions()->getLevelSeed();
|
||||
param->seed = seed = app.getLevelGenerationOptions()->getLevelSeed();
|
||||
|
||||
if(param->levelGen->isTutorial())
|
||||
{
|
||||
// Load the tutorial save data here
|
||||
if(param->levelGen->requiresBaseSave() && !param->levelGen->getBaseSavePath().empty() )
|
||||
{
|
||||
#ifdef _XBOX
|
||||
#ifdef _TU_BUILD
|
||||
wstring fileRoot = L"UPDATE:\\res\\GameRules\\" + param->levelGen->getBaseSavePath();
|
||||
#else
|
||||
wstring fileRoot = L"GAME:\\res\\TitleUpdate\\GameRules\\" + param->levelGen->getBaseSavePath();
|
||||
#endif
|
||||
#else
|
||||
#ifdef _WINDOWS64
|
||||
wstring fileRoot = L"Windows64Media\\Tutorial\\" + param->levelGen->getBaseSavePath();
|
||||
File root(fileRoot);
|
||||
if(!root.exists()) fileRoot = L"Windows64\\Tutorial\\" + param->levelGen->getBaseSavePath();
|
||||
#elif defined(__ORBIS__)
|
||||
wstring fileRoot = L"/app0/orbis/Tutorial/" + param->levelGen->getBaseSavePath();
|
||||
#elif defined(__PSVITA__)
|
||||
wstring fileRoot = L"PSVita/Tutorial/" + param->levelGen->getBaseSavePath();
|
||||
#elif defined(__PS3__)
|
||||
wstring fileRoot = L"PS3/Tutorial/" + param->levelGen->getBaseSavePath();
|
||||
#else
|
||||
wstring fileRoot = L"Tutorial\\" + param->levelGen->getBaseSavePath();
|
||||
#endif
|
||||
#endif
|
||||
File grf(fileRoot);
|
||||
if (grf.exists())
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
wstring path = grf.getPath();
|
||||
const WCHAR *pchFilename=path.c_str();
|
||||
HANDLE fileHandle = CreateFile(
|
||||
pchFilename, // file name
|
||||
GENERIC_READ, // access mode
|
||||
0, // share mode // TODO 4J Stu - Will we need to share file? Probably not but...
|
||||
NULL, // Unused
|
||||
OPEN_EXISTING , // how to create // TODO 4J Stu - Assuming that the file already exists if we are opening to read from it
|
||||
FILE_FLAG_SEQUENTIAL_SCAN, // file attributes
|
||||
NULL // Unsupported
|
||||
);
|
||||
#else
|
||||
const char *pchFilename=wstringtofilename(grf.getPath());
|
||||
HANDLE fileHandle = CreateFile(
|
||||
pchFilename, // file name
|
||||
GENERIC_READ, // access mode
|
||||
0, // share mode // TODO 4J Stu - Will we need to share file? Probably not but...
|
||||
NULL, // Unused
|
||||
OPEN_EXISTING , // how to create // TODO 4J Stu - Assuming that the file already exists if we are opening to read from it
|
||||
FILE_FLAG_SEQUENTIAL_SCAN, // file attributes
|
||||
NULL // Unsupported
|
||||
);
|
||||
#endif
|
||||
|
||||
if( fileHandle != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
DWORD bytesRead,dwFileSize = GetFileSize(fileHandle,NULL);
|
||||
PBYTE pbData = (PBYTE) new BYTE[dwFileSize];
|
||||
BOOL bSuccess = ReadFile(fileHandle,pbData,dwFileSize,&bytesRead,NULL);
|
||||
if(bSuccess==FALSE)
|
||||
{
|
||||
app.FatalLoadError();
|
||||
}
|
||||
CloseHandle(fileHandle);
|
||||
|
||||
// 4J-PB - is it possible that we can get here after a read fail and it's not an error?
|
||||
param->levelGen->setBaseSaveData(pbData, dwFileSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -694,7 +767,7 @@ int CGameNetworkManager::JoinFromInvite_SignInReturned(void *pParam,bool bContin
|
||||
{
|
||||
UINT uiIDA[1];
|
||||
uiIDA[0] = IDS_OK;
|
||||
ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad, NULL, NULL, app.GetStringTable());
|
||||
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -738,7 +811,7 @@ int CGameNetworkManager::JoinFromInvite_SignInReturned(void *pParam,bool bContin
|
||||
{
|
||||
UINT uiIDA[1];
|
||||
uiIDA[0]=IDS_CONFIRM_OK;
|
||||
ui.RequestMessageBox( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable());
|
||||
ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -856,6 +929,16 @@ int CGameNetworkManager::ServerThreadProc( void* lpParameter )
|
||||
NetworkGameInitData *param = (NetworkGameInitData *)lpParameter;
|
||||
seed = param->seed;
|
||||
app.SetGameHostOption(eGameHostOption_All,param->settings);
|
||||
|
||||
// 4J Stu - If we are loading a DLC save that's separate from the texture pack, load
|
||||
if( param->levelGen != NULL && (param->texturePackId == 0 || param->levelGen->getRequiredTexturePackId() != param->texturePackId) )
|
||||
{
|
||||
while((Minecraft::GetInstance()->skins->needsUIUpdate() || ui.IsReloadingSkin()))
|
||||
{
|
||||
Sleep(1);
|
||||
}
|
||||
param->levelGen->loadBaseSaveData();
|
||||
}
|
||||
}
|
||||
|
||||
SetThreadName(-1, "Minecraft Server thread");
|
||||
@@ -867,6 +950,7 @@ int CGameNetworkManager::ServerThreadProc( void* lpParameter )
|
||||
Entity::useSmallIds();
|
||||
Level::enableLightingCache();
|
||||
Tile::CreateNewThreadStorage();
|
||||
FireworksRecipe::CreateNewThreadStorage();
|
||||
|
||||
MinecraftServer::main(seed, lpParameter); //saveData, app.GetGameHostOption(eGameHostOption_All));
|
||||
|
||||
@@ -889,10 +973,7 @@ int CGameNetworkManager::ExitAndJoinFromInviteThreadProc( void* lpParam )
|
||||
Compression::UseDefaultThreadStorage();
|
||||
|
||||
//app.SetGameStarted(false);
|
||||
|
||||
#ifndef __PSVITA__
|
||||
UIScene_PauseMenu::_ExitWorld(NULL);
|
||||
#endif
|
||||
|
||||
while( g_NetworkManager.IsInSession() )
|
||||
{
|
||||
@@ -900,7 +981,7 @@ int CGameNetworkManager::ExitAndJoinFromInviteThreadProc( void* lpParam )
|
||||
}
|
||||
|
||||
// Xbox should always be online when receiving invites - on PS3 we need to check & ask the user to sign in
|
||||
#ifndef __PS3__
|
||||
#if !defined(__PS3__) && !defined(__PSVITA__)
|
||||
JoinFromInviteData *inviteData = (JoinFromInviteData *)lpParam;
|
||||
app.SetAction(inviteData->dwUserIndex, eAppAction_JoinFromInvite, lpParam);
|
||||
#else
|
||||
@@ -914,7 +995,7 @@ int CGameNetworkManager::ExitAndJoinFromInviteThreadProc( void* lpParam )
|
||||
UINT uiIDA[2];
|
||||
uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
|
||||
uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
|
||||
ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CGameNetworkManager::MustSignInReturned_0,lpParam, app.GetStringTable());
|
||||
ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CGameNetworkManager::MustSignInReturned_0,lpParam);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1053,16 +1134,16 @@ int CGameNetworkManager::ChangeSessionTypeThreadProc( void* lpParam )
|
||||
{
|
||||
if(g_NetworkManager.m_bSignedOutofPSN)
|
||||
{
|
||||
C4JStorage::EMessageResult result = ui.RequestMessageBox( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME, IDS_ERROR_PSN_SIGN_OUT, uiIDA,1,ProfileManager.GetPrimaryPad());
|
||||
C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME, IDS_ERROR_PSN_SIGN_OUT, uiIDA,1,ProfileManager.GetPrimaryPad());
|
||||
}
|
||||
else
|
||||
{
|
||||
C4JStorage::EMessageResult result = ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME, uiIDA,1,ProfileManager.GetPrimaryPad());
|
||||
C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME, uiIDA,1,ProfileManager.GetPrimaryPad());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
C4JStorage::EMessageResult result = ui.RequestMessageBox( IDS_CONNECTION_LOST, g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT), uiIDA,1,ProfileManager.GetPrimaryPad());
|
||||
C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_CONNECTION_LOST, g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT), uiIDA,1,ProfileManager.GetPrimaryPad());
|
||||
}
|
||||
|
||||
// Swap these two messages around as one is too long to display at 480
|
||||
@@ -1073,7 +1154,7 @@ int CGameNetworkManager::ChangeSessionTypeThreadProc( void* lpParam )
|
||||
{
|
||||
UINT uiIDA[1];
|
||||
uiIDA[0]=IDS_CONFIRM_OK;
|
||||
C4JStorage::EMessageResult result = ui.RequestMessageBox( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME, IDS_IN_PARTY_SESSION_FULL, uiIDA,1,ProfileManager.GetPrimaryPad());
|
||||
C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME, IDS_IN_PARTY_SESSION_FULL, uiIDA,1,ProfileManager.GetPrimaryPad());
|
||||
pMinecraft->progressRenderer->progressStartNoAbort( IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME );
|
||||
pMinecraft->progressRenderer->progressStage( -1 );
|
||||
}
|
||||
@@ -1215,6 +1296,13 @@ int CGameNetworkManager::ChangeSessionTypeThreadProc( void* lpParam )
|
||||
// Update the network player
|
||||
pMinecraft->m_pendingLocalConnections[index]->getConnection()->getSocket()->setPlayer(g_NetworkManager.GetLocalPlayerByUserIndex(index));
|
||||
}
|
||||
else if ( pMinecraft->m_connectionFailed[index] && (pMinecraft->m_connectionFailedReason[index] == DisconnectPacket::eDisconnect_ConnectionCreationFailed) )
|
||||
{
|
||||
pMinecraft->removeLocalPlayerIdx(index);
|
||||
#ifdef _XBOX_ONE
|
||||
ProfileManager.RemoveGamepadFromGame(index);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1572,7 +1660,7 @@ void CGameNetworkManager::GameInviteReceived( int userIndex, const INVITE_INFO *
|
||||
// 4J Stu - This is a bit messy and is due to the library incorrectly returning false for IsSignedInLive if the npAvailability isn't SCE_OK
|
||||
UINT uiIDA[1];
|
||||
uiIDA[0]=IDS_OK;
|
||||
ui.RequestMessageBox(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive, NULL, NULL, app.GetStringTable());
|
||||
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, iPadNotSignedInLive);
|
||||
}
|
||||
else if (ProfileManager.isSignedInPSN(iPadNotSignedInLive))
|
||||
{
|
||||
@@ -1581,60 +1669,39 @@ void CGameNetworkManager::GameInviteReceived( int userIndex, const INVITE_INFO *
|
||||
|
||||
UINT uiIDA[1];
|
||||
uiIDA[0] = IDS_OK;
|
||||
ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPadNotSignedInLive, NULL, NULL, app.GetStringTable());
|
||||
ui.RequestErrorMessage( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, iPadNotSignedInLive);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not signed in to PSN
|
||||
UINT uiIDA[1];
|
||||
uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT;
|
||||
ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPadNotSignedInLive, &CGameNetworkManager::MustSignInReturned_1, (void *)pInviteInfo, app.GetStringTable(), NULL, 0, false);
|
||||
ui.RequestAlertMessage( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, iPadNotSignedInLive, &CGameNetworkManager::MustSignInReturned_1, (void *)pInviteInfo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 4J-JEV: Check that all players are authorised for PsPlus, present upsell to players that aren't and try again.
|
||||
for (unsigned int index = 0; index < XUSER_MAX_COUNT; index++)
|
||||
// if this is the trial game, we'll check and send the user to unlock the game later, in HandleInviteWhenInMenus
|
||||
if(ProfileManager.IsFullVersion())
|
||||
{
|
||||
if ( ProfileManager.IsSignedIn(index)
|
||||
&& !ProfileManager.HasPlayStationPlus(userIndex) )
|
||||
// 4J-JEV: Check that all players are authorised for PsPlus, present upsell to players that aren't and try again.
|
||||
for (unsigned int index = 0; index < XUSER_MAX_COUNT; index++)
|
||||
{
|
||||
m_pInviteInfo = (INVITE_INFO *) pInviteInfo;
|
||||
m_iPlayerInvited = userIndex;
|
||||
if ( ProfileManager.IsSignedIn(index)
|
||||
&& !ProfileManager.HasPlayStationPlus(userIndex) )
|
||||
{
|
||||
m_pInviteInfo = (INVITE_INFO *) pInviteInfo;
|
||||
m_iPlayerInvited = userIndex;
|
||||
|
||||
m_pUpsell = new PsPlusUpsellWrapper(index);
|
||||
m_pUpsell->displayUpsell();
|
||||
m_pUpsell = new PsPlusUpsellWrapper(index);
|
||||
m_pUpsell->displayUpsell();
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __PSVITA__
|
||||
// Need to check we're signed in to PSN
|
||||
bool isSignedInLive = ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad());
|
||||
if (!isSignedInLive)
|
||||
{
|
||||
// Determine why they're not "signed in live"
|
||||
// MGH - we need to add a new message at some point for connecting when already signed in
|
||||
// if (ProfileManager.IsSignedInPSN(ProfileManager.GetPrimaryPad()))
|
||||
// {
|
||||
// // Signed in to PSN but not connected (no internet access)
|
||||
// UINT uiIDA[1];
|
||||
// uiIDA[0] = IDS_OK;
|
||||
// ui.RequestMessageBox( IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK, uiIDA, 1, ProfileManager.GetPrimaryPad(), NULL, NULL, app.GetStringTable());
|
||||
// }
|
||||
// else
|
||||
{
|
||||
// Not signed in to PSN
|
||||
UINT uiIDA[1];
|
||||
uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT;
|
||||
ui.RequestMessageBox( IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1, ProfileManager.GetPrimaryPad(), &CGameNetworkManager::MustSignInReturned_1, (void *)pInviteInfo, app.GetStringTable(), NULL, 0, false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int localUsersMask = 0;
|
||||
Minecraft *pMinecraft = Minecraft::GetInstance();
|
||||
@@ -1675,17 +1742,22 @@ void CGameNetworkManager::GameInviteReceived( int userIndex, const INVITE_INFO *
|
||||
uiIDA[0]=IDS_CONFIRM_OK;
|
||||
|
||||
// 4J-PB - it's possible there is no primary pad here, when accepting an invite from the dashboard
|
||||
ui.RequestMessageBox( IDS_CONNECTION_FAILED, IDS_CONNECTION_FAILED_NO_SD_SPLITSCREEN, uiIDA,1,XUSER_INDEX_ANY,NULL,NULL, app.GetStringTable());
|
||||
ui.RequestErrorMessage( IDS_CONNECTION_FAILED, IDS_CONNECTION_FAILED_NO_SD_SPLITSCREEN, uiIDA,1,XUSER_INDEX_ANY);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if( noUGC )
|
||||
{
|
||||
#ifdef __PSVITA__
|
||||
// showing the system message for chat restriction here instead now, to fix FQA bug report
|
||||
ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, ProfileManager.GetPrimaryPad() );
|
||||
#else
|
||||
int messageText = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL;
|
||||
if(joiningUsers > 1) messageText = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL;
|
||||
|
||||
ui.RequestUGCMessageBox(IDS_CONNECTION_FAILED, messageText, XUSER_INDEX_ANY);
|
||||
#endif
|
||||
}
|
||||
#if defined(__PS3__) || defined __PSVITA__
|
||||
else if(bContentRestricted)
|
||||
@@ -1703,7 +1775,7 @@ void CGameNetworkManager::GameInviteReceived( int userIndex, const INVITE_INFO *
|
||||
|
||||
// 4J-PB - it's possible there is no primary pad here, when accepting an invite from the dashboard
|
||||
//StorageManager.RequestMessageBox( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable());
|
||||
ui.RequestMessageBox( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,XUSER_INDEX_ANY,NULL,NULL, app.GetStringTable());
|
||||
ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,XUSER_INDEX_ANY);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1717,10 +1789,11 @@ void CGameNetworkManager::GameInviteReceived( int userIndex, const INVITE_INFO *
|
||||
#endif
|
||||
if( !g_NetworkManager.IsInSession() )
|
||||
{
|
||||
#ifndef __PS3__
|
||||
HandleInviteWhenInMenus(userIndex, pInviteInfo);
|
||||
#else
|
||||
#if defined (__PS3__) || defined (__PSVITA__)
|
||||
// PS3 is more complicated here - we need to make sure that the player is online. If they are then we can do the same as the xbox, if not we need to try and get them online and then, if they do sign in, go down the same path
|
||||
|
||||
// Determine why they're not "signed in live"
|
||||
// MGH - On Vita we need to add a new message at some point for connecting when already signed in
|
||||
if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()))
|
||||
{
|
||||
HandleInviteWhenInMenus(userIndex, pInviteInfo);
|
||||
@@ -1730,8 +1803,12 @@ void CGameNetworkManager::GameInviteReceived( int userIndex, const INVITE_INFO *
|
||||
UINT uiIDA[2];
|
||||
uiIDA[0]=IDS_PRO_NOTONLINE_ACCEPT;
|
||||
uiIDA[1]=IDS_PRO_NOTONLINE_DECLINE;
|
||||
ui.RequestMessageBox(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CGameNetworkManager::MustSignInReturned_1,(void *)pInviteInfo, app.GetStringTable());
|
||||
ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, ProfileManager.GetPrimaryPad(),&CGameNetworkManager::MustSignInReturned_1,(void *)pInviteInfo);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
HandleInviteWhenInMenus(userIndex, pInviteInfo);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -1777,7 +1854,9 @@ void CGameNetworkManager::HandleInviteWhenInMenus( int userIndex, const INVITE_I
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef _XBOX_ONE
|
||||
ProfileManager.SetPrimaryPad(userIndex);
|
||||
#endif
|
||||
|
||||
// 4J Stu - If we accept an invite from the main menu before going to play game we need to load the DLC
|
||||
// These checks are done within the StartInstallDLCProcess - (!app.DLCInstallProcessCompleted() && !app.DLCInstallPending()) app.StartInstallDLCProcess(dwUserIndex);
|
||||
@@ -1787,7 +1866,11 @@ void CGameNetworkManager::HandleInviteWhenInMenus( int userIndex, const INVITE_I
|
||||
// The locked profile should not be changed if we are in menus as the main player might sign out in the sign-in ui
|
||||
//ProfileManager.SetLockedProfile(-1);
|
||||
|
||||
#ifdef _XBOX_ONE
|
||||
if((!app.IsLocalMultiplayerAvailable())&&InputManager.IsPadLocked(userIndex))
|
||||
#else
|
||||
if(!app.IsLocalMultiplayerAvailable())
|
||||
#endif
|
||||
{
|
||||
bool noPrivileges=!ProfileManager.AllowedToPlayMultiplayer(userIndex);
|
||||
|
||||
@@ -1795,7 +1878,7 @@ void CGameNetworkManager::HandleInviteWhenInMenus( int userIndex, const INVITE_I
|
||||
{
|
||||
UINT uiIDA[1];
|
||||
uiIDA[0]=IDS_CONFIRM_OK;
|
||||
ui.RequestMessageBox( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad(),NULL,NULL, app.GetStringTable());
|
||||
ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,ProfileManager.GetPrimaryPad());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@ using namespace std;
|
||||
class ClientConnection;
|
||||
class Minecraft;
|
||||
|
||||
const int NON_QNET_SENDDATA_ACK_REQUIRED = 1;
|
||||
|
||||
// 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
|
||||
|
||||
@@ -9,8 +9,9 @@ class INetworkPlayer
|
||||
public:
|
||||
virtual ~INetworkPlayer() {}
|
||||
virtual unsigned char GetSmallId() = 0;
|
||||
virtual void SendData(INetworkPlayer *player, const void *pvData, int dataSize, bool lowPriority) = 0;
|
||||
virtual void SendData(INetworkPlayer *player, const void *pvData, int dataSize, bool lowPriority, bool ack) = 0;
|
||||
virtual bool IsSameSystem(INetworkPlayer *player) = 0;
|
||||
virtual int GetOutstandingAckCount() = 0;
|
||||
virtual int GetSendQueueSizeBytes( INetworkPlayer *player, bool lowPriority ) = 0;
|
||||
virtual int GetSendQueueSizeMessages( INetworkPlayer *player, bool lowPriority ) = 0;
|
||||
virtual int GetCurrentRtt() = 0;
|
||||
@@ -28,4 +29,6 @@ public:
|
||||
virtual const wchar_t *GetOnlineName() = 0;
|
||||
virtual wstring GetDisplayName() = 0;
|
||||
virtual PlayerUID GetUID() = 0;
|
||||
virtual void SentChunkPacket() = 0;
|
||||
virtual int GetTimeSinceLastChunkPacket_ms() = 0;
|
||||
};
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user