mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-04-25 15:33:38 +00:00
2210 lines
85 KiB
C++
2210 lines
85 KiB
C++
#include <thread>
|
|
#include <chrono>
|
|
|
|
#include "../../Minecraft.World/Platform/stdafx.h"
|
|
#include "../../Minecraft.World/Util/StringHelpers.h"
|
|
#include "../../Minecraft.World/Util/AABB.h"
|
|
#include "../../Minecraft.World/Util/Vec3.h"
|
|
#include "../../Minecraft.World/Network/Socket.h"
|
|
#include "../../Minecraft.World/Util/ThreadName.h"
|
|
#include "../../Minecraft.World/Entities/Entity.h"
|
|
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.h"
|
|
#include "../../Minecraft.World/Recipes/FireworksRecipe.h"
|
|
#include "../../Minecraft.Client/Network/ClientConnection.h"
|
|
#include "../../Minecraft.Client/Minecraft.h"
|
|
#include "../../Minecraft.Client/Player/User.h"
|
|
#include "../../Minecraft.Client/MinecraftServer.h"
|
|
#include "../../Minecraft.Client/Network/PlayerList.h"
|
|
#include "../../Minecraft.Client/Player/ServerPlayer.h"
|
|
#include "../../Minecraft.Client/Network/PlayerConnection.h"
|
|
#include "../../Minecraft.Client/Level/MultiPlayerLevel.h"
|
|
#include "../../Minecraft.Client/Rendering/EntityRenderers/ProgressRenderer.h"
|
|
#include "../../Minecraft.Client/Player/MultiPlayerLocalPlayer.h"
|
|
#include "../../Minecraft.World/Network/Packets/DisconnectPacket.h"
|
|
#include "../../Minecraft.World/IO/Streams/Compression.h"
|
|
#include "../../Minecraft.World/Level/Storage/OldChunkStorage.h"
|
|
#include "../../Minecraft.Client/Textures/Packs/TexturePackRepository.h"
|
|
#include "../../Minecraft.Client/Textures/Packs/TexturePack.h"
|
|
|
|
#include "../../Minecraft.Client/UI/Gui.h"
|
|
#include "../../Minecraft.Client/Rendering/LevelRenderer.h"
|
|
#include "../GameRules/ConsoleGameRules.h"
|
|
#include "GameNetworkManager.h"
|
|
|
|
#ifdef _XBOX
|
|
#include "../XUI/XUI_PauseMenu.h"
|
|
#elif !(defined __PSVITA__)
|
|
#include "../UI/UI.h"
|
|
#include "../UI/UIScene_PauseMenu.h"
|
|
#include "../../Minecraft.Client/Platform/Xbox/Network/NetworkPlayerXbox.h"
|
|
#endif
|
|
|
|
#ifdef _DURANGO
|
|
#include "../../Minecraft.World/Stats/DurangoStats.h"
|
|
#endif
|
|
|
|
// Global instance
|
|
CGameNetworkManager g_NetworkManager;
|
|
CPlatformNetworkManager* CGameNetworkManager::s_pPlatformNetworkManager;
|
|
|
|
int64_t CGameNetworkManager::messageQueue[512];
|
|
int64_t CGameNetworkManager::byteQueue[512];
|
|
int CGameNetworkManager::messageQueuePos = 0;
|
|
|
|
CGameNetworkManager::CGameNetworkManager() {
|
|
m_bInitialised = false;
|
|
m_bLastDisconnectWasLostRoomOnly = false;
|
|
m_bFullSessionMessageOnNextSessionChange = false;
|
|
|
|
#ifdef __ORBIS__
|
|
m_pUpsell = NULL;
|
|
m_pInviteInfo = NULL;
|
|
#endif
|
|
}
|
|
|
|
void CGameNetworkManager::Initialise() {
|
|
ServerStoppedCreate(false);
|
|
ServerReadyCreate(false);
|
|
int flagIndexSize =
|
|
LevelRenderer::getGlobalChunkCount() /
|
|
(Level::maxBuildHeight /
|
|
16); // dividing here by number of renderer chunks in one column
|
|
#ifdef _XBOX
|
|
s_pPlatformNetworkManager = new CPlatformNetworkManagerXbox();
|
|
#elif defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
|
|
s_pPlatformNetworkManager = new CPlatformNetworkManagerSony();
|
|
#elif defined _DURANGO
|
|
s_pPlatformNetworkManager = new CPlatformNetworkManagerDurango();
|
|
#else
|
|
s_pPlatformNetworkManager = new CPlatformNetworkManagerStub();
|
|
#endif
|
|
s_pPlatformNetworkManager->Initialise(this, flagIndexSize);
|
|
m_bNetworkThreadRunning = false;
|
|
m_bInitialised = true;
|
|
}
|
|
|
|
void CGameNetworkManager::Terminate() {
|
|
if (m_bInitialised) {
|
|
s_pPlatformNetworkManager->Terminate();
|
|
}
|
|
}
|
|
|
|
void CGameNetworkManager::DoWork() {
|
|
#ifdef _XBOX
|
|
// did we get any notifications from the game listener?
|
|
if (app.GetNotifications()->size() != 0) {
|
|
PNOTIFICATION pNotification = app.GetNotifications()->back();
|
|
|
|
switch (pNotification->dwNotification) {
|
|
case XN_LIVE_LINK_STATE_CHANGED: {
|
|
int iPrimaryPlayer = g_NetworkManager.GetPrimaryPad();
|
|
bool bConnected = (pNotification->uiParam != 0) ? true : false;
|
|
if ((g_NetworkManager.GetLockedProfile() != -1) &&
|
|
iPrimaryPlayer != -1 && bConnected == false &&
|
|
g_NetworkManager.IsInSession()) {
|
|
app.SetAction(iPrimaryPlayer,
|
|
eAppAction_EthernetDisconnected);
|
|
}
|
|
} break;
|
|
case XN_LIVE_INVITE_ACCEPTED:
|
|
s_pPlatformNetworkManager->Notify(pNotification->dwNotification,
|
|
pNotification->uiParam);
|
|
break;
|
|
}
|
|
|
|
app.GetNotifications()->pop_back();
|
|
delete pNotification;
|
|
}
|
|
#endif
|
|
s_pPlatformNetworkManager->DoWork();
|
|
|
|
#ifdef __ORBIS__
|
|
if (m_pUpsell != NULL && m_pUpsell->hasResponse()) {
|
|
int iPad_invited = m_iPlayerInvited,
|
|
iPad_checking = m_pUpsell->m_userIndex;
|
|
|
|
m_iPlayerInvited = -1;
|
|
|
|
delete m_pUpsell;
|
|
m_pUpsell = NULL;
|
|
|
|
if (ProfileManager.HasPlayStationPlus(iPad_checking)) {
|
|
this->GameInviteReceived(iPad_invited, m_pInviteInfo);
|
|
|
|
// m_pInviteInfo deleted by GameInviteReceived.
|
|
m_pInviteInfo = NULL;
|
|
} else {
|
|
delete m_pInviteInfo;
|
|
m_pInviteInfo = NULL;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
bool CGameNetworkManager::_RunNetworkGame(void* lpParameter) {
|
|
bool success = true;
|
|
|
|
bool isHost = g_NetworkManager.IsHost();
|
|
// Start the network game
|
|
Minecraft* pMinecraft = Minecraft::GetInstance();
|
|
success = StartNetworkGame(pMinecraft, lpParameter);
|
|
|
|
if (!success) return false;
|
|
|
|
if (isHost) {
|
|
// We do not have a lobby, so the only players in the game at this point
|
|
// are local ones.
|
|
|
|
success = s_pPlatformNetworkManager->_RunNetworkGame();
|
|
if (!success) {
|
|
app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_ExitWorld,
|
|
(void*)TRUE);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (g_NetworkManager.IsLeavingGame()) return false;
|
|
|
|
app.SetGameStarted(true);
|
|
|
|
// 4J-PB - if this is the trial game, start the trial timer
|
|
if (!ProfileManager.IsFullVersion()) {
|
|
ui.SetTrialTimerLimitSecs(
|
|
MinecraftDynamicConfigurations::GetTrialTime());
|
|
app.SetTrialTimerStart();
|
|
}
|
|
// app.CloseXuiScenes(ProfileManager.GetPrimaryPad());
|
|
|
|
return success;
|
|
}
|
|
|
|
bool CGameNetworkManager::StartNetworkGame(Minecraft* minecraft,
|
|
void* lpParameter) {
|
|
#ifdef _DURANGO
|
|
ProfileManager.SetDeferredSignoutEnabled(true);
|
|
#endif
|
|
|
|
int64_t seed = 0;
|
|
if (lpParameter != NULL) {
|
|
NetworkGameInitData* param = (NetworkGameInitData*)lpParameter;
|
|
seed = param->seed;
|
|
|
|
app.setLevelGenerationOptions(param->levelGen);
|
|
if (param->levelGen != NULL) {
|
|
if (app.getLevelGenerationOptions() == NULL) {
|
|
app.DebugPrintf(
|
|
"Game rule was not loaded, and seed is required. "
|
|
"Exiting.\n");
|
|
return false;
|
|
} else {
|
|
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
|
|
std::wstring fileRoot =
|
|
L"UPDATE:\\res\\GameRules\\" +
|
|
param->levelGen->getBaseSavePath();
|
|
#else
|
|
std::wstring fileRoot =
|
|
L"GAME:\\res\\TitleUpdate\\GameRules\\" +
|
|
param->levelGen->getBaseSavePath();
|
|
#endif
|
|
#else
|
|
#ifdef _WINDOWS64
|
|
std::wstring fileRoot =
|
|
L"Windows64Media\\Tutorial\\" +
|
|
param->levelGen->getBaseSavePath();
|
|
File root(fileRoot);
|
|
if (!root.exists())
|
|
fileRoot = L"Windows64\\Tutorial\\" +
|
|
param->levelGen->getBaseSavePath();
|
|
#elif defined(__ORBIS__)
|
|
std::wstring fileRoot =
|
|
L"/app0/orbis/Tutorial/" +
|
|
param->levelGen->getBaseSavePath();
|
|
#elif defined(__PSVITA__)
|
|
std::wstring fileRoot =
|
|
L"PSVita/Tutorial/" +
|
|
param->levelGen->getBaseSavePath();
|
|
#elif defined(__PS3__)
|
|
std::wstring fileRoot =
|
|
L"PS3/Tutorial/" +
|
|
param->levelGen->getBaseSavePath();
|
|
#else
|
|
std::wstring fileRoot =
|
|
L"Tutorial\\" + param->levelGen->getBaseSavePath();
|
|
#endif
|
|
#endif
|
|
File grf(fileRoot);
|
|
if (grf.exists()) {
|
|
#ifdef _UNICODE
|
|
std::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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int64_t sseed =
|
|
seed; // Create static version so this will be valid until next call to
|
|
// this function & whilst thread is running
|
|
ServerStoppedCreate(false);
|
|
if (g_NetworkManager.IsHost()) {
|
|
ServerStoppedCreate(true);
|
|
ServerReadyCreate(true);
|
|
// Ready to go - create actual networking thread & start hosting
|
|
C4JThread* thread =
|
|
new C4JThread(&CGameNetworkManager::ServerThreadProc, lpParameter,
|
|
"Server", 256 * 1024);
|
|
#if defined __PS3__ || defined __PSVITA__
|
|
thread->SetPriority(THREAD_PRIORITY_BELOW_NORMAL);
|
|
#endif //__PS3__
|
|
|
|
thread->SetProcessor(CPU_CORE_SERVER);
|
|
thread->Run();
|
|
|
|
app.DebugPrintf("[NET] Waiting for server ready...\n");
|
|
ServerReadyWait();
|
|
ServerReadyDestroy();
|
|
app.DebugPrintf("[NET] Server ready! serverHalted=%d\n",
|
|
MinecraftServer::serverHalted());
|
|
|
|
if (MinecraftServer::serverHalted()) return false;
|
|
|
|
// printf("Server ready to go!\n");
|
|
} else {
|
|
Socket::Initialise(NULL);
|
|
}
|
|
|
|
#ifndef _XBOX
|
|
Minecraft* pMinecraft = Minecraft::GetInstance();
|
|
app.DebugPrintf("[NET] IsReadyToPlayOrIdle=%d IsInSession=%d\n",
|
|
IsReadyToPlayOrIdle(), IsInSession());
|
|
// Make sure that we have transitioned through any joining/creating stages
|
|
// and are actually playing the game, so that we know the players should be
|
|
// valid
|
|
bool changedMessage = false;
|
|
while (!IsReadyToPlayOrIdle()) {
|
|
changedMessage = true;
|
|
pMinecraft->progressRenderer->progressStage(
|
|
g_NetworkManager.CorrectErrorIDS(
|
|
IDS_PROGRESS_SAVING_TO_DISC)); // "Finalizing..." vaguest
|
|
// message I could find
|
|
pMinecraft->progressRenderer->progressStagePercentage(
|
|
g_NetworkManager.GetJoiningReadyPercentage());
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
if (changedMessage) {
|
|
pMinecraft->progressRenderer->progressStagePercentage(100);
|
|
}
|
|
#endif
|
|
|
|
// If we aren't in session, then something bad must have happened - we
|
|
// aren't joining, creating or ready play
|
|
app.DebugPrintf("[NET] Checking IsInSession...=%d\n", IsInSession());
|
|
if (!IsInSession()) {
|
|
app.DebugPrintf("[NET] NOT in session! Halting server.\n");
|
|
MinecraftServer::HaltServer();
|
|
return false;
|
|
}
|
|
|
|
app.DebugPrintf("[NET] DLC check: completed=%d pending=%d\n",
|
|
app.DLCInstallProcessCompleted(), app.DLCInstallPending());
|
|
// 4J Stu - Wait a while to make sure that DLC is loaded. This is the last
|
|
// point before the network communication starts so the latest we can check
|
|
// this
|
|
while (!app.DLCInstallProcessCompleted() && app.DLCInstallPending() &&
|
|
!g_NetworkManager.IsLeavingGame()) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
if (g_NetworkManager.IsLeavingGame()) {
|
|
MinecraftServer::HaltServer();
|
|
return false;
|
|
}
|
|
|
|
// PRIMARY PLAYER
|
|
|
|
app.DebugPrintf("[NET] Creating ClientConnection (IsHost=%d)...\n",
|
|
g_NetworkManager.IsHost());
|
|
std::vector<ClientConnection*> createdConnections;
|
|
ClientConnection* connection;
|
|
|
|
if (g_NetworkManager.IsHost()) {
|
|
connection = new ClientConnection(minecraft, NULL);
|
|
app.DebugPrintf("[NET] ClientConnection created, createdOk=%d\n",
|
|
connection->createdOk);
|
|
} else {
|
|
INetworkPlayer* pNetworkPlayer =
|
|
g_NetworkManager.GetLocalPlayerByUserIndex(
|
|
ProfileManager.GetLockedProfile());
|
|
if (pNetworkPlayer == NULL) {
|
|
MinecraftServer::HaltServer();
|
|
app.DebugPrintf("%d\n", ProfileManager.GetLockedProfile());
|
|
// If the player is NULL here then something went wrong in the
|
|
// session setup, and continuing will end up in a crash
|
|
return false;
|
|
}
|
|
|
|
Socket* socket = pNetworkPlayer->GetSocket();
|
|
|
|
// Fix for #13259 - CRASH: Gameplay: loading process is halted when
|
|
// player loads saved data
|
|
if (socket == NULL) {
|
|
assert(false);
|
|
MinecraftServer::HaltServer();
|
|
// If the socket is NULL here then something went wrong in the
|
|
// session setup, and continuing will end up in a crash
|
|
return false;
|
|
}
|
|
|
|
connection = new ClientConnection(minecraft, socket);
|
|
}
|
|
|
|
if (!connection->createdOk) {
|
|
assert(false);
|
|
delete connection;
|
|
connection = NULL;
|
|
MinecraftServer::HaltServer();
|
|
return false;
|
|
}
|
|
|
|
app.DebugPrintf("[NET] Sending PreLoginPacket...\n");
|
|
connection->send(std::shared_ptr<PreLoginPacket>(
|
|
new PreLoginPacket(minecraft->user->name)));
|
|
app.DebugPrintf(
|
|
"[NET] PreLoginPacket sent. Entering connection tick loop...\n");
|
|
|
|
// Tick connection until we're ready to go. The stages involved in this are:
|
|
// (1) Creating the ClientConnection sends a prelogin packet to the server
|
|
// (2) the server sends a prelogin back, which is handled by the
|
|
// clientConnection, and returns a login packet (3) the server sends a login
|
|
// back, which is handled by the client connection to start the game
|
|
if (!g_NetworkManager.IsHost()) {
|
|
Minecraft::GetInstance()->progressRenderer->progressStart(
|
|
IDS_PROGRESS_CONNECTING);
|
|
} else {
|
|
// 4J Stu - Host needs to generate a unique multiplayer id for sentient
|
|
// telemetry reporting
|
|
int multiplayerInstanceId =
|
|
TelemetryManager->GenerateMultiplayerInstanceId();
|
|
TelemetryManager->SetMultiplayerInstanceId(multiplayerInstanceId);
|
|
}
|
|
TexturePack* tPack = Minecraft::GetInstance()->skins->getSelected();
|
|
do {
|
|
app.DebugPrintf("ticking connection A\n");
|
|
connection->tick();
|
|
|
|
// 4J Stu - We were ticking this way too fast which could cause the
|
|
// connection to time out The connections should tick at 20 per second
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
} while ((IsInSession() && !connection->isStarted() &&
|
|
!connection->isClosed() && !g_NetworkManager.IsLeavingGame()) ||
|
|
tPack->isLoadingData() ||
|
|
(Minecraft::GetInstance()->skins->needsUIUpdate() ||
|
|
ui.IsReloadingSkin()));
|
|
ui.CleanUpSkinReload();
|
|
|
|
// 4J Stu - Fix for #11279 - CRASH: TCR 001: BAS Game Stability: Signing out
|
|
// of game will cause title to crash We need to break out of the above loop
|
|
// if m_bLeavingGame is set, and close the connection
|
|
if (g_NetworkManager.IsLeavingGame() || !IsInSession()) {
|
|
connection->close();
|
|
}
|
|
|
|
if (connection->isStarted() && !connection->isClosed()) {
|
|
createdConnections.push_back(connection);
|
|
|
|
int primaryPad = ProfileManager.GetPrimaryPad();
|
|
app.SetRichPresenceContext(primaryPad, CONTEXT_GAME_STATE_BLANK);
|
|
if (GetPlayerCount() >
|
|
1) // Are we offline or online, and how many players are there
|
|
{
|
|
if (IsLocalGame())
|
|
ProfileManager.SetCurrentGameActivity(
|
|
primaryPad, CONTEXT_PRESENCE_MULTIPLAYEROFFLINE, false);
|
|
else
|
|
ProfileManager.SetCurrentGameActivity(
|
|
primaryPad, CONTEXT_PRESENCE_MULTIPLAYER, false);
|
|
} else {
|
|
if (IsLocalGame())
|
|
ProfileManager.SetCurrentGameActivity(
|
|
primaryPad, CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE, false);
|
|
else
|
|
ProfileManager.SetCurrentGameActivity(
|
|
primaryPad, CONTEXT_PRESENCE_MULTIPLAYER_1P, false);
|
|
}
|
|
|
|
// ALL OTHER LOCAL PLAYERS
|
|
for (int idx = 0; idx < XUSER_MAX_COUNT; ++idx) {
|
|
// Already have setup the primary pad
|
|
if (idx == ProfileManager.GetPrimaryPad()) continue;
|
|
|
|
if (GetLocalPlayerByUserIndex(idx) != NULL &&
|
|
!ProfileManager.IsSignedIn(idx)) {
|
|
INetworkPlayer* pNetworkPlayer =
|
|
g_NetworkManager.GetLocalPlayerByUserIndex(idx);
|
|
Socket* socket = pNetworkPlayer->GetSocket();
|
|
app.DebugPrintf(
|
|
"Closing socket due to player %d not being signed in any "
|
|
"more\n");
|
|
if (!socket->close(false)) socket->close(true);
|
|
|
|
continue;
|
|
}
|
|
|
|
// By default when we host we only have the local player, but
|
|
// currently allow multiple local players to join when joining any
|
|
// other way, so just because they are signed in doesn't mean they
|
|
// are in the session 4J Stu - If they are in the session, then we
|
|
// should add them to the game. Otherwise we won't be able to add
|
|
// them later
|
|
INetworkPlayer* pNetworkPlayer =
|
|
g_NetworkManager.GetLocalPlayerByUserIndex(idx);
|
|
if (pNetworkPlayer == NULL) continue;
|
|
|
|
ClientConnection* connection;
|
|
|
|
Socket* socket = pNetworkPlayer->GetSocket();
|
|
connection = new ClientConnection(minecraft, socket, idx);
|
|
|
|
minecraft->addPendingLocalConnection(idx, connection);
|
|
// minecraft->createExtraLocalPlayer(idx, (convStringToWstring(
|
|
// ProfileManager.GetGamertag(idx) )).c_str(), idx, connection);
|
|
|
|
// Open the socket on the server end to accept incoming data
|
|
Socket::addIncomingSocket(socket);
|
|
|
|
connection->send(std::shared_ptr<PreLoginPacket>(new PreLoginPacket(
|
|
convStringToWstring(ProfileManager.GetGamertag(idx)))));
|
|
|
|
createdConnections.push_back(connection);
|
|
|
|
// Tick connection until we're ready to go. The stages involved in
|
|
// this are: (1) Creating the ClientConnection sends a prelogin
|
|
// packet to the server (2) the server sends a prelogin back, which
|
|
// is handled by the clientConnection, and returns a login packet
|
|
// (3) the server sends a login back, which is handled by the client
|
|
// connection to start the game
|
|
do {
|
|
// We need to keep ticking the connections for players that
|
|
// already logged in
|
|
for (AUTO_VAR(it, createdConnections.begin());
|
|
it < createdConnections.end(); ++it) {
|
|
(*it)->tick();
|
|
}
|
|
|
|
// 4J Stu - We were ticking this way too fast which could cause
|
|
// the connection to time out The connections should tick at 20
|
|
// per second
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
app.DebugPrintf("<***> %d %d %d %d %d\n", IsInSession(),
|
|
!connection->isStarted(),
|
|
!connection->isClosed(),
|
|
ProfileManager.IsSignedIn(idx),
|
|
!g_NetworkManager.IsLeavingGame());
|
|
#if defined _XBOX || __PS3__
|
|
} while (IsInSession() && !connection->isStarted() &&
|
|
!connection->isClosed() &&
|
|
ProfileManager.IsSignedIn(idx) &&
|
|
!g_NetworkManager.IsLeavingGame());
|
|
#else
|
|
// TODO - This SHOULD be something just like the code above but
|
|
// temporarily changing here so that we don't have to depend on
|
|
// the profilemanager behaviour
|
|
} while (IsInSession() && !connection->isStarted() &&
|
|
!connection->isClosed() &&
|
|
!g_NetworkManager.IsLeavingGame());
|
|
#endif
|
|
|
|
// 4J Stu - Fix for #11279 - CRASH: TCR 001: BAS Game Stability:
|
|
// Signing out of game will cause title to crash We need to break
|
|
// out of the above loop if m_bLeavingGame is set, and stop creating
|
|
// new connections The connections in the createdConnections vector
|
|
// get closed at the end of the thread
|
|
if (g_NetworkManager.IsLeavingGame() || !IsInSession()) break;
|
|
|
|
if (ProfileManager.IsSignedIn(idx) && !connection->isClosed()) {
|
|
app.SetRichPresenceContext(idx, CONTEXT_GAME_STATE_BLANK);
|
|
if (IsLocalGame())
|
|
ProfileManager.SetCurrentGameActivity(
|
|
idx, CONTEXT_PRESENCE_MULTIPLAYEROFFLINE, false);
|
|
else
|
|
ProfileManager.SetCurrentGameActivity(
|
|
idx, CONTEXT_PRESENCE_MULTIPLAYER, false);
|
|
} else {
|
|
connection->close();
|
|
AUTO_VAR(it, find(createdConnections.begin(),
|
|
createdConnections.end(), connection));
|
|
if (it != createdConnections.end())
|
|
createdConnections.erase(it);
|
|
}
|
|
}
|
|
|
|
app.SetGameMode(eMode_Multiplayer);
|
|
} else if (connection->isClosed() || !IsInSession()) {
|
|
// assert(false);
|
|
MinecraftServer::HaltServer();
|
|
return false;
|
|
}
|
|
|
|
if (g_NetworkManager.IsLeavingGame() || !IsInSession()) {
|
|
for (AUTO_VAR(it, createdConnections.begin());
|
|
it < createdConnections.end(); ++it) {
|
|
(*it)->close();
|
|
}
|
|
// assert(false);
|
|
MinecraftServer::HaltServer();
|
|
return false;
|
|
}
|
|
|
|
// Catch in-case server has been halted (by a player signout).
|
|
if (MinecraftServer::serverHalted()) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
int CGameNetworkManager::CorrectErrorIDS(int IDS) {
|
|
return s_pPlatformNetworkManager->CorrectErrorIDS(IDS);
|
|
}
|
|
|
|
int CGameNetworkManager::GetLocalPlayerMask(int playerIndex) {
|
|
return s_pPlatformNetworkManager->GetLocalPlayerMask(playerIndex);
|
|
}
|
|
|
|
int CGameNetworkManager::GetPlayerCount() {
|
|
return s_pPlatformNetworkManager->GetPlayerCount();
|
|
}
|
|
|
|
int CGameNetworkManager::GetOnlinePlayerCount() {
|
|
return s_pPlatformNetworkManager->GetOnlinePlayerCount();
|
|
}
|
|
|
|
bool CGameNetworkManager::AddLocalPlayerByUserIndex(int userIndex) {
|
|
return s_pPlatformNetworkManager->AddLocalPlayerByUserIndex(userIndex);
|
|
}
|
|
|
|
bool CGameNetworkManager::RemoveLocalPlayerByUserIndex(int userIndex) {
|
|
return s_pPlatformNetworkManager->RemoveLocalPlayerByUserIndex(userIndex);
|
|
}
|
|
|
|
INetworkPlayer* CGameNetworkManager::GetLocalPlayerByUserIndex(int userIndex) {
|
|
return s_pPlatformNetworkManager->GetLocalPlayerByUserIndex(userIndex);
|
|
}
|
|
|
|
INetworkPlayer* CGameNetworkManager::GetPlayerByIndex(int playerIndex) {
|
|
return s_pPlatformNetworkManager->GetPlayerByIndex(playerIndex);
|
|
}
|
|
|
|
INetworkPlayer* CGameNetworkManager::GetPlayerByXuid(PlayerUID xuid) {
|
|
return s_pPlatformNetworkManager->GetPlayerByXuid(xuid);
|
|
}
|
|
|
|
INetworkPlayer* CGameNetworkManager::GetPlayerBySmallId(unsigned char smallId) {
|
|
return s_pPlatformNetworkManager->GetPlayerBySmallId(smallId);
|
|
}
|
|
|
|
#ifdef _DURANGO
|
|
std::wstring CGameNetworkManager::GetDisplayNameByGamertag(
|
|
std::wstring gamertag) {
|
|
return s_pPlatformNetworkManager->GetDisplayNameByGamertag(gamertag);
|
|
}
|
|
#endif
|
|
|
|
INetworkPlayer* CGameNetworkManager::GetHostPlayer() {
|
|
return s_pPlatformNetworkManager->GetHostPlayer();
|
|
}
|
|
|
|
void CGameNetworkManager::RegisterPlayerChangedCallback(
|
|
int iPad,
|
|
void (*callback)(void* callbackParam, INetworkPlayer* pPlayer,
|
|
bool leaving),
|
|
void* callbackParam) {
|
|
s_pPlatformNetworkManager->RegisterPlayerChangedCallback(iPad, callback,
|
|
callbackParam);
|
|
}
|
|
|
|
void CGameNetworkManager::UnRegisterPlayerChangedCallback(
|
|
int iPad,
|
|
void (*callback)(void* callbackParam, INetworkPlayer* pPlayer,
|
|
bool leaving),
|
|
void* callbackParam) {
|
|
s_pPlatformNetworkManager->UnRegisterPlayerChangedCallback(iPad, callback,
|
|
callbackParam);
|
|
}
|
|
|
|
void CGameNetworkManager::HandleSignInChange() {
|
|
s_pPlatformNetworkManager->HandleSignInChange();
|
|
}
|
|
|
|
bool CGameNetworkManager::ShouldMessageForFullSession() {
|
|
return s_pPlatformNetworkManager->ShouldMessageForFullSession();
|
|
}
|
|
|
|
bool CGameNetworkManager::IsInSession() {
|
|
return s_pPlatformNetworkManager->IsInSession();
|
|
}
|
|
|
|
bool CGameNetworkManager::IsInGameplay() {
|
|
return s_pPlatformNetworkManager->IsInGameplay();
|
|
}
|
|
|
|
bool CGameNetworkManager::IsReadyToPlayOrIdle() {
|
|
return s_pPlatformNetworkManager->IsReadyToPlayOrIdle();
|
|
}
|
|
|
|
bool CGameNetworkManager::IsLeavingGame() {
|
|
return s_pPlatformNetworkManager->IsLeavingGame();
|
|
}
|
|
|
|
bool CGameNetworkManager::SetLocalGame(bool isLocal) {
|
|
return s_pPlatformNetworkManager->SetLocalGame(isLocal);
|
|
}
|
|
|
|
bool CGameNetworkManager::IsLocalGame() {
|
|
return s_pPlatformNetworkManager->IsLocalGame();
|
|
}
|
|
|
|
void CGameNetworkManager::SetPrivateGame(bool isPrivate) {
|
|
s_pPlatformNetworkManager->SetPrivateGame(isPrivate);
|
|
}
|
|
|
|
bool CGameNetworkManager::IsPrivateGame() {
|
|
return s_pPlatformNetworkManager->IsPrivateGame();
|
|
}
|
|
|
|
void CGameNetworkManager::HostGame(int localUsersMask, bool bOnlineGame,
|
|
bool bIsPrivate, unsigned char publicSlots,
|
|
unsigned char privateSlots) {
|
|
// 4J Stu - clear any previous connection errors
|
|
Minecraft::GetInstance()->clearConnectionFailed();
|
|
|
|
s_pPlatformNetworkManager->HostGame(localUsersMask, bOnlineGame, bIsPrivate,
|
|
publicSlots, privateSlots);
|
|
}
|
|
|
|
bool CGameNetworkManager::IsHost() {
|
|
return (s_pPlatformNetworkManager->IsHost() == TRUE);
|
|
}
|
|
|
|
bool CGameNetworkManager::IsInStatsEnabledSession() {
|
|
return s_pPlatformNetworkManager->IsInStatsEnabledSession();
|
|
}
|
|
|
|
bool CGameNetworkManager::SessionHasSpace(unsigned int spaceRequired) {
|
|
return s_pPlatformNetworkManager->SessionHasSpace(spaceRequired);
|
|
}
|
|
|
|
std::vector<FriendSessionInfo*>* CGameNetworkManager::GetSessionList(
|
|
int iPad, int localPlayers, bool partyOnly) {
|
|
return s_pPlatformNetworkManager->GetSessionList(iPad, localPlayers,
|
|
partyOnly);
|
|
}
|
|
|
|
bool CGameNetworkManager::GetGameSessionInfo(int iPad, SessionID sessionId,
|
|
FriendSessionInfo* foundSession) {
|
|
return s_pPlatformNetworkManager->GetGameSessionInfo(iPad, sessionId,
|
|
foundSession);
|
|
}
|
|
|
|
void CGameNetworkManager::SetSessionsUpdatedCallback(
|
|
void (*SessionsUpdatedCallback)(void* pParam), void* pSearchParam) {
|
|
s_pPlatformNetworkManager->SetSessionsUpdatedCallback(
|
|
SessionsUpdatedCallback, pSearchParam);
|
|
}
|
|
|
|
void CGameNetworkManager::GetFullFriendSessionInfo(
|
|
FriendSessionInfo* foundSession,
|
|
void (*FriendSessionUpdatedFn)(bool success, void* pParam), void* pParam) {
|
|
s_pPlatformNetworkManager->GetFullFriendSessionInfo(
|
|
foundSession, FriendSessionUpdatedFn, pParam);
|
|
}
|
|
|
|
void CGameNetworkManager::ForceFriendsSessionRefresh() {
|
|
s_pPlatformNetworkManager->ForceFriendsSessionRefresh();
|
|
}
|
|
|
|
bool CGameNetworkManager::JoinGameFromInviteInfo(
|
|
int userIndex, int userMask, const INVITE_INFO* pInviteInfo) {
|
|
return s_pPlatformNetworkManager->JoinGameFromInviteInfo(
|
|
userIndex, userMask, pInviteInfo);
|
|
}
|
|
|
|
CGameNetworkManager::eJoinGameResult CGameNetworkManager::JoinGame(
|
|
FriendSessionInfo* searchResult, int localUsersMask) {
|
|
app.SetTutorialMode(false);
|
|
g_NetworkManager.SetLocalGame(false);
|
|
|
|
int primaryUserIndex = ProfileManager.GetLockedProfile();
|
|
|
|
// 4J-PB - clear any previous connection errors
|
|
Minecraft::GetInstance()->clearConnectionFailed();
|
|
|
|
// Make sure that the Primary Pad is in by default
|
|
localUsersMask |= GetLocalPlayerMask(ProfileManager.GetPrimaryPad());
|
|
|
|
return (eJoinGameResult)(s_pPlatformNetworkManager->JoinGame(
|
|
searchResult, localUsersMask, primaryUserIndex));
|
|
}
|
|
|
|
void CGameNetworkManager::CancelJoinGame(void* lpParam) {
|
|
#ifdef _XBOX_ONE
|
|
s_pPlatformNetworkManager->CancelJoinGame();
|
|
#endif
|
|
}
|
|
|
|
bool CGameNetworkManager::LeaveGame(bool bMigrateHost) {
|
|
Minecraft::GetInstance()->gui->clearMessages();
|
|
return s_pPlatformNetworkManager->LeaveGame(bMigrateHost);
|
|
}
|
|
|
|
int CGameNetworkManager::JoinFromInvite_SignInReturned(void* pParam,
|
|
bool bContinue,
|
|
int iPad) {
|
|
INVITE_INFO* pInviteInfo = (INVITE_INFO*)pParam;
|
|
|
|
if (bContinue == true) {
|
|
#ifdef __ORBIS__
|
|
// Check if PSN is unavailable because of age restriction
|
|
int npAvailability = ProfileManager.getNPAvailability(iPad);
|
|
if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) {
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0] = IDS_OK;
|
|
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE,
|
|
IDS_CONTENT_RESTRICTION, uiIDA, 1, iPad);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
app.DebugPrintf("JoinFromInvite_SignInReturned, iPad %d\n", iPad);
|
|
// It's possible that the player has not signed in - they can back out
|
|
if (ProfileManager.IsSignedIn(iPad) &&
|
|
ProfileManager.IsSignedInLive(iPad)) {
|
|
app.DebugPrintf(
|
|
"JoinFromInvite_SignInReturned, passed sign-in tests\n");
|
|
int localUsersMask = 0;
|
|
int joiningUsers = 0;
|
|
|
|
bool noPrivileges = false;
|
|
for (unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) {
|
|
if (ProfileManager.IsSignedIn(index)) {
|
|
++joiningUsers;
|
|
if (!ProfileManager.AllowedToPlayMultiplayer(index))
|
|
noPrivileges = true;
|
|
localUsersMask |= GetLocalPlayerMask(index);
|
|
}
|
|
}
|
|
|
|
// Check if user-created content is allowed, as we cannot play
|
|
// multiplayer if it's not
|
|
bool noUGC = false;
|
|
#if defined(__PS3__) || defined(__PSVITA__)
|
|
ProfileManager.GetChatAndContentRestrictions(iPad, false, &noUGC,
|
|
NULL, NULL);
|
|
#elif defined(__ORBIS__)
|
|
ProfileManager.GetChatAndContentRestrictions(iPad, false, NULL,
|
|
&noUGC, NULL);
|
|
#endif
|
|
|
|
if (noUGC) {
|
|
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);
|
|
} else if (noPrivileges) {
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0] = IDS_CONFIRM_OK;
|
|
ui.RequestErrorMessage(IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE,
|
|
IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT,
|
|
uiIDA, 1,
|
|
ProfileManager.GetPrimaryPad());
|
|
} else {
|
|
#if defined(__ORBIS__) || defined(__PSVITA__)
|
|
bool chatRestricted = false;
|
|
ProfileManager.GetChatAndContentRestrictions(
|
|
iPad, false, &chatRestricted, NULL, NULL);
|
|
if (chatRestricted) {
|
|
ProfileManager.DisplaySystemMessage(
|
|
0, ProfileManager.GetPrimaryPad());
|
|
}
|
|
#endif
|
|
ProfileManager.SetLockedProfile(iPad);
|
|
ProfileManager.SetPrimaryPad(iPad);
|
|
|
|
g_NetworkManager.SetLocalGame(false);
|
|
|
|
// If the player was signed in before selecting play, we'll not
|
|
// have read the profile yet, so query the sign-in status to get
|
|
// this to happen
|
|
ProfileManager.QuerySigninStatus();
|
|
|
|
// 4J-PB - clear any previous connection errors
|
|
Minecraft::GetInstance()->clearConnectionFailed();
|
|
|
|
// change the minecraft player name
|
|
Minecraft::GetInstance()->user->name = convStringToWstring(
|
|
ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad()));
|
|
|
|
bool success = g_NetworkManager.JoinGameFromInviteInfo(
|
|
iPad, // dwUserIndex
|
|
localUsersMask, // dwUserMask
|
|
pInviteInfo); // pInviteInfo
|
|
if (!success) {
|
|
app.DebugPrintf("Failed joining game from invite\n");
|
|
}
|
|
}
|
|
} else {
|
|
app.DebugPrintf(
|
|
"JoinFromInvite_SignInReturned, failed sign-in tests :%d %d\n",
|
|
ProfileManager.IsSignedIn(iPad),
|
|
ProfileManager.IsSignedInLive(iPad));
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CGameNetworkManager::UpdateAndSetGameSessionData(
|
|
INetworkPlayer* pNetworkPlayerLeaving) {
|
|
Minecraft* pMinecraft = Minecraft::GetInstance();
|
|
TexturePack* tPack = pMinecraft->skins->getSelected();
|
|
s_pPlatformNetworkManager->SetSessionTexturePackParentId(
|
|
tPack->getDLCParentPackId());
|
|
s_pPlatformNetworkManager->SetSessionSubTexturePackId(
|
|
tPack->getDLCSubPackId());
|
|
|
|
s_pPlatformNetworkManager->UpdateAndSetGameSessionData(
|
|
pNetworkPlayerLeaving);
|
|
}
|
|
|
|
void CGameNetworkManager::SendInviteGUI(int quadrant) {
|
|
s_pPlatformNetworkManager->SendInviteGUI(quadrant);
|
|
}
|
|
|
|
void CGameNetworkManager::ResetLeavingGame() {
|
|
s_pPlatformNetworkManager->ResetLeavingGame();
|
|
}
|
|
|
|
bool CGameNetworkManager::IsNetworkThreadRunning() {
|
|
return m_bNetworkThreadRunning;
|
|
;
|
|
}
|
|
|
|
int CGameNetworkManager::RunNetworkGameThreadProc(void* lpParameter) {
|
|
// Share AABB & Vec3 pools with default (main thread) - should be ok as long
|
|
// as we don't tick the main thread whilst this thread is running
|
|
Compression::UseDefaultThreadStorage();
|
|
Tile::CreateNewThreadStorage();
|
|
|
|
g_NetworkManager.m_bNetworkThreadRunning = true;
|
|
bool success = g_NetworkManager._RunNetworkGame(lpParameter);
|
|
g_NetworkManager.m_bNetworkThreadRunning = false;
|
|
if (!success) {
|
|
TexturePack* tPack = Minecraft::GetInstance()->skins->getSelected();
|
|
while (tPack->isLoadingData() ||
|
|
(Minecraft::GetInstance()->skins->needsUIUpdate() ||
|
|
ui.IsReloadingSkin())) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
}
|
|
ui.CleanUpSkinReload();
|
|
if (app.GetDisconnectReason() == DisconnectPacket::eDisconnect_None) {
|
|
app.SetDisconnectReason(
|
|
DisconnectPacket::eDisconnect_ConnectionCreationFailed);
|
|
}
|
|
// If we failed before the server started, clear the game rules.
|
|
// Otherwise the server will clear it up.
|
|
if (MinecraftServer::getInstance() == NULL)
|
|
app.m_gameRules.unloadCurrentGameRules();
|
|
Tile::ReleaseThreadStorage();
|
|
return -1;
|
|
}
|
|
|
|
#ifdef __PSVITA__
|
|
// 4J-JEV: Wait for the loading/saving to finish.
|
|
while (StorageManager.GetSaveState() != C4JStorage::ESaveGame_Idle)
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
#endif
|
|
|
|
Tile::ReleaseThreadStorage();
|
|
return 0;
|
|
}
|
|
|
|
int CGameNetworkManager::ServerThreadProc(void* lpParameter) {
|
|
int64_t seed = 0;
|
|
if (lpParameter != NULL) {
|
|
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())) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
}
|
|
param->levelGen->loadBaseSaveData();
|
|
}
|
|
}
|
|
|
|
SetThreadName(-1, "Minecraft Server thread");
|
|
Compression::UseDefaultThreadStorage();
|
|
OldChunkStorage::UseDefaultThreadStorage();
|
|
Entity::useSmallIds();
|
|
Level::enableLightingCache();
|
|
Tile::CreateNewThreadStorage();
|
|
FireworksRecipe::CreateNewThreadStorage();
|
|
|
|
MinecraftServer::main(
|
|
seed,
|
|
lpParameter); // saveData, app.GetGameHostOption(eGameHostOption_All));
|
|
|
|
Tile::ReleaseThreadStorage();
|
|
Level::destroyLightingCache();
|
|
|
|
if (lpParameter != NULL) delete (NetworkGameInitData*)lpParameter;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
int CGameNetworkManager::ExitAndJoinFromInviteThreadProc(void* lpParam) {
|
|
// Share AABB & Vec3 pools with default (main thread) - should be ok as long
|
|
// as we don't tick the main thread whilst this thread is running
|
|
Compression::UseDefaultThreadStorage();
|
|
|
|
// app.SetGameStarted(false);
|
|
UIScene_PauseMenu::_ExitWorld(NULL);
|
|
|
|
while (g_NetworkManager.IsInSession()) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
}
|
|
|
|
// Xbox should always be online when receiving invites - on PS3 we need to
|
|
// check & ask the user to sign in
|
|
#if !defined(__PS3__) && !defined(__PSVITA__)
|
|
JoinFromInviteData* inviteData = (JoinFromInviteData*)lpParam;
|
|
app.SetAction(inviteData->dwUserIndex, eAppAction_JoinFromInvite, lpParam);
|
|
#else
|
|
if (ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())) {
|
|
JoinFromInviteData* inviteData = (JoinFromInviteData*)lpParam;
|
|
app.SetAction(inviteData->dwUserIndex, eAppAction_JoinFromInvite,
|
|
lpParam);
|
|
} else {
|
|
unsigned int uiIDA[2];
|
|
uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT;
|
|
uiIDA[1] = IDS_PRO_NOTONLINE_DECLINE;
|
|
ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT,
|
|
uiIDA, 2, ProfileManager.GetPrimaryPad(),
|
|
&CGameNetworkManager::MustSignInReturned_0,
|
|
lpParam);
|
|
}
|
|
#endif
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__
|
|
// This case happens when we have been returned from the game to the main menu
|
|
// after receiving an invite and are now trying to go back in to join the new
|
|
// game The pair of methods MustSignInReturned_0 & PSNSignInReturned_0 handle
|
|
// this
|
|
int CGameNetworkManager::MustSignInReturned_0(
|
|
void* pParam, int iPad, C4JStorage::EMessageResult result) {
|
|
if (result == C4JStorage::EMessage_ResultAccept) {
|
|
#ifdef __PS3__
|
|
SQRNetworkManager_PS3::AttemptPSNSignIn(
|
|
&CGameNetworkManager::PSNSignInReturned_0, pParam, true);
|
|
#elif defined __PSVITA__
|
|
SQRNetworkManager_Vita::AttemptPSNSignIn(
|
|
&CGameNetworkManager::PSNSignInReturned_0, pParam, true);
|
|
#elif defined __ORBIS__
|
|
SQRNetworkManager_Orbis::AttemptPSNSignIn(
|
|
&CGameNetworkManager::PSNSignInReturned_0, pParam, true);
|
|
#endif
|
|
} else {
|
|
app.SetAction(0, eAppAction_Idle);
|
|
ui.NavigateToHomeMenu();
|
|
ui.UpdatePlayerBasePositions();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CGameNetworkManager::PSNSignInReturned_0(void* pParam, bool bContinue,
|
|
int iPad) {
|
|
JoinFromInviteData* inviteData = (JoinFromInviteData*)pParam;
|
|
|
|
// If the invite data isn't set up yet (indicated by it being all zeroes,
|
|
// easiest detected via the net version), then try and get it again... this
|
|
// can happen if we got the invite whilst signed out
|
|
|
|
if (bContinue) {
|
|
if (inviteData->pInviteInfo->netVersion == 0) {
|
|
#if defined __PS3__ || defined __VITA__
|
|
if (!SQRNetworkManager_PS3::UpdateInviteData(
|
|
(SQRNetworkManager::PresenceSyncInfo*)
|
|
inviteData->pInviteInfo)) {
|
|
bContinue = false;
|
|
}
|
|
#elif defined __ORBIS__
|
|
// TODO: No Orbis equivalent (should there be?)
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (bContinue) {
|
|
app.SetAction(inviteData->dwUserIndex, eAppAction_JoinFromInvite,
|
|
pParam);
|
|
} else {
|
|
app.SetAction(inviteData->dwUserIndex, eAppAction_Idle);
|
|
ui.NavigateToHomeMenu();
|
|
ui.UpdatePlayerBasePositions();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// This case happens when we were in the main menus when we got an invite, and
|
|
// weren't signed in... now can proceed with the normal flow of code for this
|
|
// situation The pair of methods MustSignInReturned_1 & PSNSignInReturned_1
|
|
// handle this
|
|
int CGameNetworkManager::MustSignInReturned_1(
|
|
void* pParam, int iPad, C4JStorage::EMessageResult result) {
|
|
if (result == C4JStorage::EMessage_ResultAccept) {
|
|
#ifdef __PS3__
|
|
SQRNetworkManager_PS3::AttemptPSNSignIn(
|
|
&CGameNetworkManager::PSNSignInReturned_1, pParam, true);
|
|
#elif defined __PSVITA__
|
|
SQRNetworkManager_Vita::AttemptPSNSignIn(
|
|
&CGameNetworkManager::PSNSignInReturned_1, pParam, true);
|
|
#elif defined __ORBIS__
|
|
SQRNetworkManager_Orbis::AttemptPSNSignIn(
|
|
&CGameNetworkManager::PSNSignInReturned_1, pParam, true);
|
|
#endif
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int CGameNetworkManager::PSNSignInReturned_1(void* pParam, bool bContinue,
|
|
int iPad) {
|
|
INVITE_INFO* inviteInfo = (INVITE_INFO*)pParam;
|
|
|
|
// If the invite data isn't set up yet (indicated by it being all zeroes,
|
|
// easiest detected via the net version), then try and get it again... this
|
|
// can happen if we got the invite whilst signed out
|
|
|
|
if (bContinue) {
|
|
if (inviteInfo->netVersion == 0) {
|
|
#if defined __PS3__ || defined __VITA__
|
|
if (!SQRNetworkManager_PS3::UpdateInviteData(
|
|
(SQRNetworkManager::PresenceSyncInfo*)inviteInfo)) {
|
|
bContinue = false;
|
|
}
|
|
#elif defined __ORBIS__
|
|
// TODO: No Orbis equivalent (should there be?)
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (bContinue) {
|
|
g_NetworkManager.HandleInviteWhenInMenus(0, inviteInfo);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
void CGameNetworkManager::_LeaveGame() {
|
|
s_pPlatformNetworkManager->_LeaveGame(false, true);
|
|
}
|
|
|
|
int CGameNetworkManager::ChangeSessionTypeThreadProc(void* lpParam) {
|
|
// Share AABB & Vec3 pools with default (main thread) - should be ok as long
|
|
// as we don't tick the main thread whilst this thread is running
|
|
Compression::UseDefaultThreadStorage();
|
|
|
|
Minecraft* pMinecraft = Minecraft::GetInstance();
|
|
MinecraftServer* pServer = MinecraftServer::getInstance();
|
|
|
|
#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0] = IDS_CONFIRM_OK;
|
|
if (g_NetworkManager.m_bLastDisconnectWasLostRoomOnly) {
|
|
if (g_NetworkManager.m_bSignedOutofPSN) {
|
|
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.RequestErrorMessage(
|
|
IDS_ERROR_NETWORK_TITLE,
|
|
IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME, uiIDA, 1,
|
|
ProfileManager.GetPrimaryPad());
|
|
}
|
|
} else {
|
|
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
|
|
pMinecraft->progressRenderer->progressStartNoAbort(
|
|
IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME);
|
|
pMinecraft->progressRenderer->progressStage(
|
|
-1); // g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT)
|
|
// );
|
|
#elif defined(_XBOX_ONE)
|
|
if (g_NetworkManager.m_bFullSessionMessageOnNextSessionChange) {
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0] = IDS_CONFIRM_OK;
|
|
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);
|
|
} else {
|
|
pMinecraft->progressRenderer->progressStartNoAbort(
|
|
g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT));
|
|
pMinecraft->progressRenderer->progressStage(
|
|
IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME);
|
|
}
|
|
|
|
#else
|
|
pMinecraft->progressRenderer->progressStartNoAbort(
|
|
g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT));
|
|
pMinecraft->progressRenderer->progressStage(
|
|
IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME);
|
|
#endif
|
|
|
|
while (app.GetXuiServerAction(ProfileManager.GetPrimaryPad()) !=
|
|
eXuiServerAction_Idle &&
|
|
!MinecraftServer::serverHalted()) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),
|
|
eXuiServerAction_PauseServer, (void*)TRUE);
|
|
|
|
// wait for the server to be in a non-ticking state
|
|
pServer->m_serverPausedEvent->WaitForSignal(INFINITE);
|
|
|
|
#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__
|
|
// Swap these two messages around as one is too long to display at 480
|
|
pMinecraft->progressRenderer->progressStartNoAbort(
|
|
IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME);
|
|
pMinecraft->progressRenderer->progressStage(
|
|
-1); // g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT)
|
|
// );
|
|
#elif defined(_XBOX_ONE)
|
|
if (g_NetworkManager.m_bFullSessionMessageOnNextSessionChange) {
|
|
pMinecraft->progressRenderer->progressStartNoAbort(
|
|
IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME);
|
|
pMinecraft->progressRenderer->progressStage(-1);
|
|
} else {
|
|
pMinecraft->progressRenderer->progressStartNoAbort(
|
|
g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT));
|
|
pMinecraft->progressRenderer->progressStage(
|
|
IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME);
|
|
}
|
|
#else
|
|
pMinecraft->progressRenderer->progressStartNoAbort(
|
|
g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT));
|
|
pMinecraft->progressRenderer->progressStage(
|
|
IDS_PROGRESS_CONVERTING_TO_OFFLINE_GAME);
|
|
#endif
|
|
|
|
pMinecraft->progressRenderer->progressStagePercentage(25);
|
|
|
|
#ifdef _XBOX_ONE
|
|
// wait for any players that were being added, to finish doing this. On XB1,
|
|
// if we don't do this then there's an async thread running doing this,
|
|
// which could then finish at any inappropriate time later
|
|
while (s_pPlatformNetworkManager->IsAddingPlayer()) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
}
|
|
#endif
|
|
|
|
// Null the network player of all the server players that are local, to stop
|
|
// them being removed from the server when removed from the session
|
|
if (pServer != NULL) {
|
|
PlayerList* players = pServer->getPlayers();
|
|
for (AUTO_VAR(it, players->players.begin());
|
|
it < players->players.end(); ++it) {
|
|
std::shared_ptr<ServerPlayer> servPlayer = *it;
|
|
if (servPlayer->connection->isLocal() &&
|
|
!servPlayer->connection->isGuest()) {
|
|
servPlayer->connection->connection->getSocket()->setPlayer(
|
|
NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
// delete the current session - if we weren't actually disconnected fully
|
|
// from the network but have just lost our room, then pass a bLeaveRoom flag
|
|
// of false here as by definition we don't need to leave the room (again).
|
|
// This is currently only an issue for sony platforms.
|
|
if (g_NetworkManager.m_bLastDisconnectWasLostRoomOnly) {
|
|
s_pPlatformNetworkManager->_LeaveGame(false, false);
|
|
} else {
|
|
s_pPlatformNetworkManager->_LeaveGame(false, true);
|
|
}
|
|
|
|
// wait for the current session to end
|
|
while (g_NetworkManager.IsInSession()) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
}
|
|
|
|
// Reset this flag as the we don't need to know that we only lost the room
|
|
// only from this point onwards, the behaviour is exactly the same
|
|
g_NetworkManager.m_bLastDisconnectWasLostRoomOnly = false;
|
|
g_NetworkManager.m_bFullSessionMessageOnNextSessionChange = false;
|
|
|
|
pMinecraft->progressRenderer->progressStagePercentage(50);
|
|
|
|
// Defaulting to making this a local game
|
|
g_NetworkManager.SetLocalGame(true);
|
|
|
|
// Create a new session with all the players that were in the old one
|
|
int localUsersMask = 0;
|
|
char numLocalPlayers = 0;
|
|
for (unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) {
|
|
if (ProfileManager.IsSignedIn(index) &&
|
|
pMinecraft->localplayers[index] != NULL) {
|
|
numLocalPlayers++;
|
|
localUsersMask |= GetLocalPlayerMask(index);
|
|
}
|
|
}
|
|
|
|
s_pPlatformNetworkManager->_HostGame(localUsersMask);
|
|
|
|
pMinecraft->progressRenderer->progressStagePercentage(75);
|
|
|
|
// Wait for all the local players to rejoin the session
|
|
while (g_NetworkManager.GetPlayerCount() < numLocalPlayers) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
}
|
|
|
|
// Restore the network player of all the server players that are local
|
|
if (pServer != NULL) {
|
|
for (unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) {
|
|
if (ProfileManager.IsSignedIn(index) &&
|
|
pMinecraft->localplayers[index] != NULL) {
|
|
PlayerUID localPlayerXuid =
|
|
pMinecraft->localplayers[index]->getXuid();
|
|
|
|
PlayerList* players = pServer->getPlayers();
|
|
for (AUTO_VAR(it, players->players.begin());
|
|
it < players->players.end(); ++it) {
|
|
std::shared_ptr<ServerPlayer> servPlayer = *it;
|
|
if (servPlayer->getXuid() == localPlayerXuid) {
|
|
servPlayer->connection->connection->getSocket()
|
|
->setPlayer(
|
|
g_NetworkManager.GetLocalPlayerByUserIndex(
|
|
index));
|
|
}
|
|
}
|
|
|
|
// Player might have a pending connection
|
|
if (pMinecraft->m_pendingLocalConnections[index] != NULL) {
|
|
// 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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pMinecraft->progressRenderer->progressStagePercentage(100);
|
|
|
|
#ifndef _XBOX
|
|
// Make sure that we have transitioned through any joining/creating stages
|
|
// so we're actually ready to set to play
|
|
while (!s_pPlatformNetworkManager->IsReadyToPlayOrIdle()) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
#endif
|
|
|
|
s_pPlatformNetworkManager->_StartGame();
|
|
|
|
#ifndef _XBOX
|
|
// Wait until the message box has been closed
|
|
while (ui.IsSceneInStack(XUSER_INDEX_ANY, eUIScene_MessageBox)) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
#endif
|
|
|
|
// Start the game again
|
|
app.SetGameStarted(true);
|
|
app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),
|
|
eXuiServerAction_PauseServer, (void*)FALSE);
|
|
app.SetChangingSessionType(false);
|
|
app.SetReallyChangingSessionType(false);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CGameNetworkManager::SystemFlagSet(INetworkPlayer* pNetworkPlayer,
|
|
int index) {
|
|
s_pPlatformNetworkManager->SystemFlagSet(pNetworkPlayer, index);
|
|
}
|
|
|
|
bool CGameNetworkManager::SystemFlagGet(INetworkPlayer* pNetworkPlayer,
|
|
int index) {
|
|
return s_pPlatformNetworkManager->SystemFlagGet(pNetworkPlayer, index);
|
|
}
|
|
|
|
std::wstring CGameNetworkManager::GatherStats() {
|
|
return s_pPlatformNetworkManager->GatherStats();
|
|
}
|
|
|
|
void CGameNetworkManager::renderQueueMeter() {
|
|
#ifdef _XBOX
|
|
int height = 720;
|
|
|
|
CGameNetworkManager::byteQueue[(CGameNetworkManager::messageQueuePos) &
|
|
(CGameNetworkManager::messageQueue_length -
|
|
1)] =
|
|
GetHostPlayer()->GetSendQueueSizeBytes(NULL, false);
|
|
CGameNetworkManager::messageQueue
|
|
[(CGameNetworkManager::messageQueuePos++) &
|
|
(CGameNetworkManager::messageQueue_length - 1)] =
|
|
GetHostPlayer()->GetSendQueueSizeMessages(NULL, false);
|
|
|
|
Minecraft* pMinecraft = Minecraft::GetInstance();
|
|
pMinecraft->gui->renderGraph(CGameNetworkManager::messageQueue_length,
|
|
CGameNetworkManager::messageQueuePos,
|
|
CGameNetworkManager::messageQueue, 10, 1000,
|
|
CGameNetworkManager::byteQueue, 100, 25000);
|
|
#endif
|
|
}
|
|
|
|
std::wstring CGameNetworkManager::GatherRTTStats() {
|
|
return s_pPlatformNetworkManager->GatherRTTStats();
|
|
}
|
|
|
|
void CGameNetworkManager::StateChange_AnyToHosting() {
|
|
app.DebugPrintf("Disabling Guest Signin\n");
|
|
XEnableGuestSignin(FALSE);
|
|
Minecraft::GetInstance()->clearPendingClientTextureRequests();
|
|
}
|
|
|
|
void CGameNetworkManager::StateChange_AnyToJoining() {
|
|
app.DebugPrintf("Disabling Guest Signin\n");
|
|
XEnableGuestSignin(FALSE);
|
|
Minecraft::GetInstance()->clearPendingClientTextureRequests();
|
|
|
|
ConnectionProgressParams* param = new ConnectionProgressParams();
|
|
param->iPad = ProfileManager.GetPrimaryPad();
|
|
param->stringId = -1;
|
|
param->showTooltips = false;
|
|
param->setFailTimer = true;
|
|
param->timerTime = CONNECTING_PROGRESS_CHECK_TIME;
|
|
|
|
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),
|
|
eUIScene_ConnectingProgress, param);
|
|
}
|
|
|
|
void CGameNetworkManager::StateChange_JoiningToIdle(
|
|
CPlatformNetworkManager::eJoinFailedReason reason) {
|
|
DisconnectPacket::eDisconnectReason disconnectReason;
|
|
switch (reason) {
|
|
case CPlatformNetworkManager::JOIN_FAILED_SERVER_FULL:
|
|
disconnectReason = DisconnectPacket::eDisconnect_ServerFull;
|
|
break;
|
|
case CPlatformNetworkManager::JOIN_FAILED_INSUFFICIENT_PRIVILEGES:
|
|
disconnectReason =
|
|
DisconnectPacket::eDisconnect_NoMultiplayerPrivilegesJoin;
|
|
app.SetAction(ProfileManager.GetPrimaryPad(),
|
|
eAppAction_FailedToJoinNoPrivileges);
|
|
break;
|
|
default:
|
|
disconnectReason =
|
|
DisconnectPacket::eDisconnect_ConnectionCreationFailed;
|
|
break;
|
|
};
|
|
Minecraft::GetInstance()->connectionDisconnected(
|
|
ProfileManager.GetPrimaryPad(), disconnectReason);
|
|
}
|
|
|
|
void CGameNetworkManager::StateChange_AnyToStarting() {
|
|
#if defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
|
|
app.getRemoteStorage()->shutdown(); // shut the remote storage lib down and
|
|
// hopefully get our 7mb back
|
|
#endif
|
|
|
|
if (!g_NetworkManager.IsHost()) {
|
|
LoadingInputParams* loadingParams = new LoadingInputParams();
|
|
loadingParams->func = &CGameNetworkManager::RunNetworkGameThreadProc;
|
|
loadingParams->lpParam = NULL;
|
|
|
|
UIFullscreenProgressCompletionData* completionData =
|
|
new UIFullscreenProgressCompletionData();
|
|
completionData->bShowBackground = TRUE;
|
|
completionData->bShowLogo = TRUE;
|
|
completionData->type = e_ProgressCompletion_CloseAllPlayersUIScenes;
|
|
completionData->iPad = ProfileManager.GetPrimaryPad();
|
|
loadingParams->completionData = completionData;
|
|
|
|
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),
|
|
eUIScene_FullscreenProgress, loadingParams);
|
|
}
|
|
}
|
|
|
|
void CGameNetworkManager::StateChange_AnyToEnding(bool bStateWasPlaying) {
|
|
// Kick off a stats write for players that are signed into LIVE, if this is
|
|
// a local game
|
|
if (bStateWasPlaying && g_NetworkManager.IsLocalGame()) {
|
|
for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) {
|
|
INetworkPlayer* pNetworkPlayer =
|
|
g_NetworkManager.GetLocalPlayerByUserIndex(i);
|
|
if (pNetworkPlayer != NULL && ProfileManager.IsSignedIn(i)) {
|
|
app.DebugPrintf(
|
|
"Stats save for an offline game for the player at index "
|
|
"%d\n",
|
|
i);
|
|
Minecraft::GetInstance()->forceStatsSave(
|
|
pNetworkPlayer->GetUserIndex());
|
|
}
|
|
}
|
|
}
|
|
|
|
Minecraft::GetInstance()->gui->clearMessages();
|
|
|
|
if (!g_NetworkManager.IsHost() && !g_NetworkManager.IsLeavingGame()) {
|
|
// 4J Stu - If the host is saving then it might take a while to quite
|
|
// the session, so do it ourself
|
|
// m_bLeavingGame = true;
|
|
|
|
// The host has notified that the game is about to end
|
|
if (app.GetDisconnectReason() == DisconnectPacket::eDisconnect_None)
|
|
app.SetDisconnectReason(DisconnectPacket::eDisconnect_Quitting);
|
|
app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_ExitWorld,
|
|
(void*)TRUE);
|
|
}
|
|
}
|
|
|
|
void CGameNetworkManager::StateChange_AnyToIdle() {
|
|
app.DebugPrintf("Enabling Guest Signin\n");
|
|
XEnableGuestSignin(TRUE);
|
|
// Reset this here so that we can search for games again
|
|
// 4J Stu - If we are changing session type there is a race between that
|
|
// thread setting the game to local, and this setting it to not local
|
|
if (!app.GetChangingSessionType()) g_NetworkManager.SetLocalGame(false);
|
|
}
|
|
|
|
void CGameNetworkManager::CreateSocket(INetworkPlayer* pNetworkPlayer,
|
|
bool localPlayer) {
|
|
Minecraft* pMinecraft = Minecraft::GetInstance();
|
|
|
|
Socket* socket = NULL;
|
|
std::shared_ptr<MultiplayerLocalPlayer> mpPlayer =
|
|
pMinecraft->localplayers[pNetworkPlayer->GetUserIndex()];
|
|
if (localPlayer && mpPlayer != NULL && mpPlayer->connection != NULL) {
|
|
// If we already have a MultiplayerLocalPlayer here then we are doing a
|
|
// session type change
|
|
socket = mpPlayer->connection->getSocket();
|
|
|
|
// Pair this socket and network player
|
|
pNetworkPlayer->SetSocket(socket);
|
|
if (socket) {
|
|
socket->setPlayer(pNetworkPlayer);
|
|
}
|
|
} else {
|
|
socket = new Socket(pNetworkPlayer, g_NetworkManager.IsHost(),
|
|
g_NetworkManager.IsHost() && localPlayer);
|
|
pNetworkPlayer->SetSocket(socket);
|
|
|
|
// 4J Stu - May be other states we want to accept aswell
|
|
// Add this user to the game server if the game is started already
|
|
if (g_NetworkManager.IsHost() && g_NetworkManager.IsInGameplay()) {
|
|
Socket::addIncomingSocket(socket);
|
|
}
|
|
|
|
// If this is a local player and we are already in the game, we need to
|
|
// setup a local connection and log the player in to the game server
|
|
if (localPlayer && g_NetworkManager.IsInGameplay()) {
|
|
int idx = pNetworkPlayer->GetUserIndex();
|
|
app.DebugPrintf("Creating new client connection for idx: %d\n",
|
|
idx);
|
|
|
|
ClientConnection* connection;
|
|
connection = new ClientConnection(pMinecraft, socket, idx);
|
|
|
|
if (connection->createdOk) {
|
|
connection->send(std::shared_ptr<PreLoginPacket>(
|
|
new PreLoginPacket(pNetworkPlayer->GetOnlineName())));
|
|
pMinecraft->addPendingLocalConnection(idx, connection);
|
|
} else {
|
|
pMinecraft->connectionDisconnected(
|
|
idx,
|
|
DisconnectPacket::eDisconnect_ConnectionCreationFailed);
|
|
delete connection;
|
|
connection = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CGameNetworkManager::CloseConnection(INetworkPlayer* pNetworkPlayer) {
|
|
MinecraftServer* server = MinecraftServer::getInstance();
|
|
if (server != NULL) {
|
|
PlayerList* players = server->getPlayers();
|
|
if (players != NULL) {
|
|
players->closePlayerConnectionBySmallId(
|
|
pNetworkPlayer->GetSmallId());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CGameNetworkManager::PlayerJoining(INetworkPlayer* pNetworkPlayer) {
|
|
if (g_NetworkManager
|
|
.IsInGameplay()) // 4J-JEV: Wait to do this at StartNetworkGame if
|
|
// not in-game yet.
|
|
{
|
|
// 4J-JEV: Update RichPresence when a player joins the game.
|
|
bool multiplayer = g_NetworkManager.GetPlayerCount() > 1,
|
|
localgame = g_NetworkManager.IsLocalGame();
|
|
for (int iPad = 0; iPad < XUSER_MAX_COUNT; ++iPad) {
|
|
INetworkPlayer* pNetworkPlayer =
|
|
g_NetworkManager.GetLocalPlayerByUserIndex(iPad);
|
|
if (pNetworkPlayer == NULL) continue;
|
|
|
|
app.SetRichPresenceContext(iPad, CONTEXT_GAME_STATE_BLANK);
|
|
if (multiplayer) {
|
|
if (localgame)
|
|
ProfileManager.SetCurrentGameActivity(
|
|
iPad, CONTEXT_PRESENCE_MULTIPLAYEROFFLINE, false);
|
|
else
|
|
ProfileManager.SetCurrentGameActivity(
|
|
iPad, CONTEXT_PRESENCE_MULTIPLAYER, false);
|
|
} else {
|
|
if (localgame)
|
|
ProfileManager.SetCurrentGameActivity(
|
|
iPad, CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE, false);
|
|
else
|
|
ProfileManager.SetCurrentGameActivity(
|
|
iPad, CONTEXT_PRESENCE_MULTIPLAYER_1P, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pNetworkPlayer->IsLocal()) {
|
|
TelemetryManager->RecordPlayerSessionStart(
|
|
pNetworkPlayer->GetUserIndex());
|
|
}
|
|
#ifdef _XBOX
|
|
else {
|
|
if (!pNetworkPlayer->IsHost()) {
|
|
for (int idx = 0; idx < XUSER_MAX_COUNT; ++idx) {
|
|
if (Minecraft::GetInstance()->localplayers[idx] != NULL) {
|
|
TelemetryManager->RecordLevelStart(
|
|
idx, eSen_FriendOrMatch_Playing_With_Invited_Friends,
|
|
eSen_CompeteOrCoop_Coop_and_Competitive,
|
|
Minecraft::GetInstance()->level->difficulty,
|
|
app.GetLocalPlayerCount(),
|
|
g_NetworkManager.GetOnlinePlayerCount());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CGameNetworkManager::PlayerLeaving(INetworkPlayer* pNetworkPlayer) {
|
|
if (pNetworkPlayer->IsLocal()) {
|
|
ProfileManager.SetCurrentGameActivity(pNetworkPlayer->GetUserIndex(),
|
|
CONTEXT_PRESENCE_IDLE, false);
|
|
|
|
TelemetryManager->RecordPlayerSessionExit(
|
|
pNetworkPlayer->GetUserIndex(), app.GetDisconnectReason());
|
|
}
|
|
#ifdef _XBOX
|
|
else {
|
|
for (int idx = 0; idx < XUSER_MAX_COUNT; ++idx) {
|
|
if (Minecraft::GetInstance()->localplayers[idx] != NULL) {
|
|
TelemetryManager->RecordLevelStart(
|
|
idx, eSen_FriendOrMatch_Playing_With_Invited_Friends,
|
|
eSen_CompeteOrCoop_Coop_and_Competitive,
|
|
Minecraft::GetInstance()->level->difficulty,
|
|
app.GetLocalPlayerCount(),
|
|
g_NetworkManager.GetOnlinePlayerCount());
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CGameNetworkManager::HostChanged() {
|
|
// Disable host migration
|
|
app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_ExitWorld,
|
|
(void*)TRUE);
|
|
}
|
|
|
|
void CGameNetworkManager::WriteStats(INetworkPlayer* pNetworkPlayer) {
|
|
Minecraft::GetInstance()->forceStatsSave(pNetworkPlayer->GetUserIndex());
|
|
}
|
|
|
|
void CGameNetworkManager::GameInviteReceived(int userIndex,
|
|
const INVITE_INFO* pInviteInfo) {
|
|
#ifdef __ORBIS__
|
|
if (m_pUpsell != NULL) {
|
|
delete pInviteInfo;
|
|
return;
|
|
}
|
|
|
|
// Need to check we're signed in to PSN
|
|
bool isSignedInLive = true;
|
|
bool isLocalMultiplayerAvailable = app.IsLocalMultiplayerAvailable();
|
|
int iPadNotSignedInLive = -1;
|
|
for (unsigned int i = 0; i < XUSER_MAX_COUNT; i++) {
|
|
if (ProfileManager.IsSignedIn(i) &&
|
|
(i == ProfileManager.GetPrimaryPad() ||
|
|
isLocalMultiplayerAvailable)) {
|
|
if (isSignedInLive && !ProfileManager.IsSignedInLive(i)) {
|
|
// Record the first non signed in live pad
|
|
iPadNotSignedInLive = i;
|
|
}
|
|
|
|
isSignedInLive = isSignedInLive && ProfileManager.IsSignedInLive(i);
|
|
}
|
|
}
|
|
|
|
if (!isSignedInLive) {
|
|
// Determine why they're not "signed in live"
|
|
|
|
// Check if PSN is unavailable because of age restriction
|
|
int npAvailability =
|
|
ProfileManager.getNPAvailability(iPadNotSignedInLive);
|
|
if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) {
|
|
// 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
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0] = IDS_OK;
|
|
ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE,
|
|
IDS_CONTENT_RESTRICTION, uiIDA, 1,
|
|
iPadNotSignedInLive);
|
|
} else if (ProfileManager.isSignedInPSN(iPadNotSignedInLive)) {
|
|
// Signed in to PSN but not connected (no internet access)
|
|
assert(!ProfileManager.isConnectedToPSN(iPadNotSignedInLive));
|
|
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0] = IDS_OK;
|
|
ui.RequestErrorMessage(IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK,
|
|
uiIDA, 1, iPadNotSignedInLive);
|
|
} else {
|
|
// Not signed in to PSN
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT;
|
|
ui.RequestAlertMessage(
|
|
IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 1,
|
|
iPadNotSignedInLive, &CGameNetworkManager::MustSignInReturned_1,
|
|
(void*)pInviteInfo);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// if this is the trial game, we'll check and send the user to unlock the
|
|
// game later, in HandleInviteWhenInMenus
|
|
if (ProfileManager.IsFullVersion()) {
|
|
// 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 (ProfileManager.IsSignedIn(index) &&
|
|
!ProfileManager.HasPlayStationPlus(userIndex)) {
|
|
m_pInviteInfo = (INVITE_INFO*)pInviteInfo;
|
|
m_iPlayerInvited = userIndex;
|
|
|
|
m_pUpsell = new PsPlusUpsellWrapper(index);
|
|
m_pUpsell->displayUpsell();
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
int localUsersMask = 0;
|
|
Minecraft* pMinecraft = Minecraft::GetInstance();
|
|
int joiningUsers = 0;
|
|
|
|
bool noPrivileges = false;
|
|
for (unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) {
|
|
if (ProfileManager.IsSignedIn(index)) {
|
|
// 4J-PB we shouldn't bring any inactive players into the game,
|
|
// except for the invited player (who may be an inactive player) 4J
|
|
// Stu - If we are not in a game, then bring in all players signed
|
|
// in
|
|
if (index == userIndex || pMinecraft->localplayers[index] != NULL) {
|
|
++joiningUsers;
|
|
if (!ProfileManager.AllowedToPlayMultiplayer(index))
|
|
noPrivileges = true;
|
|
localUsersMask |= GetLocalPlayerMask(index);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check if user-created content is allowed, as we cannot play multiplayer
|
|
// if it's not
|
|
bool noUGC = false;
|
|
bool bContentRestricted = false;
|
|
bool pccAllowed = true;
|
|
bool pccFriendsAllowed = true;
|
|
#if defined(__PS3__) || defined(__PSVITA__)
|
|
ProfileManager.GetChatAndContentRestrictions(userIndex, false, &noUGC,
|
|
&bContentRestricted, NULL);
|
|
#else
|
|
ProfileManager.AllowedPlayerCreatedContent(
|
|
ProfileManager.GetPrimaryPad(), false, &pccAllowed, &pccFriendsAllowed);
|
|
if (!pccAllowed && !pccFriendsAllowed) noUGC = true;
|
|
#endif
|
|
|
|
#if defined(_XBOX) || defined(__PS3__)
|
|
if (joiningUsers > 1 && !RenderManager.IsHiDef() &&
|
|
userIndex != ProfileManager.GetPrimaryPad()) {
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0] = IDS_CONFIRM_OK;
|
|
|
|
// 4J-PB - it's possible there is no primary pad here, when accepting an
|
|
// invite from the dashboard
|
|
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) {
|
|
int messageText = IDS_CONTENT_RESTRICTION;
|
|
if (joiningUsers > 1) messageText = IDS_CONTENT_RESTRICTION_MULTIPLAYER;
|
|
|
|
ui.RequestContentRestrictedMessageBox(IDS_CONNECTION_FAILED,
|
|
messageText, XUSER_INDEX_ANY);
|
|
}
|
|
#endif
|
|
else if (noPrivileges) {
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0] = IDS_CONFIRM_OK;
|
|
|
|
// 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.RequestErrorMessage(IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE,
|
|
IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA, 1,
|
|
XUSER_INDEX_ANY);
|
|
} else {
|
|
#if defined(__ORBIS__) || defined(__PSVITA__)
|
|
bool chatRestricted = false;
|
|
ProfileManager.GetChatAndContentRestrictions(
|
|
ProfileManager.GetPrimaryPad(), false, &chatRestricted, NULL, NULL);
|
|
if (chatRestricted) {
|
|
ProfileManager.DisplaySystemMessage(
|
|
SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION,
|
|
ProfileManager.GetPrimaryPad());
|
|
}
|
|
#endif
|
|
if (!g_NetworkManager.IsInSession()) {
|
|
#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);
|
|
} else {
|
|
unsigned int uiIDA[2];
|
|
uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT;
|
|
uiIDA[1] = IDS_PRO_NOTONLINE_DECLINE;
|
|
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 {
|
|
app.DebugPrintf(
|
|
"We are already in a multiplayer game...need to leave it\n");
|
|
|
|
// JoinFromInviteData *joinData = new
|
|
// JoinFromInviteData(); joinData->dwUserIndex =
|
|
// dwUserIndex; joinData->dwLocalUsersMask =
|
|
// dwLocalUsersMask; joinData->pInviteInfo =
|
|
// pInviteInfo;
|
|
|
|
// tell the app to process this
|
|
#ifdef __PSVITA__
|
|
if (((CPlatformNetworkManagerSony*)s_pPlatformNetworkManager)
|
|
->checkValidInviteData(pInviteInfo))
|
|
#endif
|
|
{
|
|
app.ProcessInvite(userIndex, localUsersMask, pInviteInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
volatile bool waitHere = true;
|
|
|
|
void CGameNetworkManager::HandleInviteWhenInMenus(
|
|
int userIndex, const INVITE_INFO* pInviteInfo) {
|
|
// We are in the root menus somewhere
|
|
|
|
#if 0
|
|
while( waitHere )
|
|
{
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
}
|
|
#endif
|
|
|
|
// if this is the trial game, then we need the user to unlock the full game
|
|
if (!ProfileManager.IsFullVersion()) {
|
|
// The marketplace will fail with the primary player set to -1
|
|
ProfileManager.SetPrimaryPad(userIndex);
|
|
|
|
app.SetAction(userIndex, eAppAction_DashboardTrialJoinFromInvite);
|
|
} 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);
|
|
app.StartInstallDLCProcess(userIndex);
|
|
|
|
// 4J Stu - Fix for #10936 - MP Lab: TCR 001: Matchmaking: Player is
|
|
// stuck in a soft-locked state after selecting the guest account when
|
|
// prompted 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);
|
|
|
|
if (noPrivileges) {
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0] = IDS_CONFIRM_OK;
|
|
ui.RequestErrorMessage(IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE,
|
|
IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT,
|
|
uiIDA, 1,
|
|
ProfileManager.GetPrimaryPad());
|
|
} else {
|
|
ProfileManager.SetLockedProfile(userIndex);
|
|
ProfileManager.SetPrimaryPad(userIndex);
|
|
|
|
int localUsersMask = 0;
|
|
localUsersMask |= GetLocalPlayerMask(userIndex);
|
|
|
|
// If the player was signed in before selecting play, we'll not
|
|
// have read the profile yet, so query the sign-in status to get
|
|
// this to happen
|
|
ProfileManager.QuerySigninStatus();
|
|
|
|
// 4J-PB - clear any previous connection errors
|
|
Minecraft::GetInstance()->clearConnectionFailed();
|
|
|
|
g_NetworkManager.SetLocalGame(false);
|
|
|
|
// change the minecraft player name
|
|
Minecraft::GetInstance()->user->name = convStringToWstring(
|
|
ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad()));
|
|
|
|
bool success = g_NetworkManager.JoinGameFromInviteInfo(
|
|
userIndex, localUsersMask, pInviteInfo);
|
|
if (!success) {
|
|
app.DebugPrintf("Failed joining game from invite\n");
|
|
}
|
|
}
|
|
} else {
|
|
// the FromInvite will make the lib decide how many panes to display
|
|
// based on connected pads/signed in players
|
|
#ifdef _XBOX
|
|
ProfileManager.RequestSignInUI(
|
|
true, false, false, false, false,
|
|
&CGameNetworkManager::JoinFromInvite_SignInReturned,
|
|
(void*)pInviteInfo, userIndex);
|
|
#else
|
|
SignInInfo info;
|
|
info.Func = &CGameNetworkManager::JoinFromInvite_SignInReturned;
|
|
info.lpParam = (void*)pInviteInfo;
|
|
info.requireOnline = true;
|
|
app.DebugPrintf("Using fullscreen layer\n");
|
|
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),
|
|
eUIScene_QuadrantSignin, &info, eUILayer_Alert,
|
|
eUIGroup_Fullscreen);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
void CGameNetworkManager::AddLocalPlayerFailed(int idx,
|
|
bool serverFull /* = false*/) {
|
|
Minecraft::GetInstance()->connectionDisconnected(
|
|
idx, serverFull
|
|
? DisconnectPacket::eDisconnect_ServerFull
|
|
: DisconnectPacket::eDisconnect_ConnectionCreationFailed);
|
|
}
|
|
|
|
#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__
|
|
void CGameNetworkManager::HandleDisconnect(bool bLostRoomOnly, bool bPSNSignout)
|
|
#else
|
|
void CGameNetworkManager::HandleDisconnect(bool bLostRoomOnly)
|
|
#endif
|
|
{
|
|
int iPrimaryPlayer = g_NetworkManager.GetPrimaryPad();
|
|
|
|
if ((g_NetworkManager.GetLockedProfile() != -1) && iPrimaryPlayer != -1 &&
|
|
g_NetworkManager.IsInSession()) {
|
|
m_bLastDisconnectWasLostRoomOnly = bLostRoomOnly;
|
|
#if defined __PS3__ || defined __PSVITA__ || defined __ORBIS__
|
|
m_bSignedOutofPSN = bPSNSignout;
|
|
#endif
|
|
app.SetAction(iPrimaryPlayer, eAppAction_EthernetDisconnected);
|
|
} else {
|
|
m_bLastDisconnectWasLostRoomOnly = false;
|
|
}
|
|
}
|
|
|
|
int CGameNetworkManager::GetPrimaryPad() {
|
|
return ProfileManager.GetPrimaryPad();
|
|
}
|
|
|
|
int CGameNetworkManager::GetLockedProfile() {
|
|
return ProfileManager.GetLockedProfile();
|
|
}
|
|
|
|
bool CGameNetworkManager::IsSignedInLive(int playerIdx) {
|
|
return ProfileManager.IsSignedInLive(playerIdx);
|
|
}
|
|
|
|
bool CGameNetworkManager::AllowedToPlayMultiplayer(int playerIdx) {
|
|
return ProfileManager.AllowedToPlayMultiplayer(playerIdx);
|
|
}
|
|
|
|
char* CGameNetworkManager::GetOnlineName(int playerIdx) {
|
|
return ProfileManager.GetGamertag(playerIdx);
|
|
}
|
|
|
|
void CGameNetworkManager::ServerReadyCreate(bool create) {
|
|
m_hServerReadyEvent = (create ? (new C4JThread::Event) : NULL);
|
|
}
|
|
|
|
void CGameNetworkManager::ServerReady() {
|
|
if (m_hServerReadyEvent != NULL) {
|
|
m_hServerReadyEvent->Set();
|
|
} else {
|
|
app.DebugPrintf(
|
|
"[NET] Warning: ServerReady() called but m_hServerReadyEvent is "
|
|
"NULL\n");
|
|
}
|
|
}
|
|
|
|
void CGameNetworkManager::ServerReadyWait() {
|
|
if (m_hServerReadyEvent != NULL) {
|
|
m_hServerReadyEvent->WaitForSignal(INFINITE);
|
|
} else {
|
|
app.DebugPrintf(
|
|
"[NET] Warning: ServerReadyWait() called but m_hServerReadyEvent "
|
|
"is NULL\n");
|
|
}
|
|
}
|
|
|
|
void CGameNetworkManager::ServerReadyDestroy() {
|
|
delete m_hServerReadyEvent;
|
|
m_hServerReadyEvent = NULL;
|
|
}
|
|
|
|
bool CGameNetworkManager::ServerReadyValid() {
|
|
return (m_hServerReadyEvent != NULL);
|
|
}
|
|
|
|
void CGameNetworkManager::ServerStoppedCreate(bool create) {
|
|
m_hServerStoppedEvent = (create ? (new C4JThread::Event) : NULL);
|
|
}
|
|
|
|
void CGameNetworkManager::ServerStopped() {
|
|
if (m_hServerStoppedEvent != NULL) {
|
|
m_hServerStoppedEvent->Set();
|
|
} else {
|
|
app.DebugPrintf(
|
|
"[NET] Warning: ServerStopped() called but m_hServerStoppedEvent "
|
|
"is NULL\n");
|
|
}
|
|
}
|
|
|
|
void CGameNetworkManager::ServerStoppedWait() {
|
|
// If this is called from the main thread, then this won't be ticking
|
|
// anything which can mean that the storage manager state can't progress.
|
|
// This means that the server thread we are waiting on won't ever finish, as
|
|
// it might be locked waiting for this to complete itself. Do some ticking
|
|
// here then if this is the case.
|
|
if (C4JThread::isMainThread()) {
|
|
int result = WAIT_TIMEOUT;
|
|
do {
|
|
#ifndef _XBOX
|
|
RenderManager.StartFrame();
|
|
#endif
|
|
result = m_hServerStoppedEvent->WaitForSignal(20);
|
|
// Tick some simple things
|
|
ProfileManager.Tick();
|
|
StorageManager.Tick();
|
|
InputManager.Tick();
|
|
RenderManager.Tick();
|
|
ui.tick();
|
|
ui.render();
|
|
RenderManager.Present();
|
|
} while (result == WAIT_TIMEOUT);
|
|
} else {
|
|
if (m_hServerStoppedEvent != NULL) {
|
|
m_hServerStoppedEvent->WaitForSignal(INFINITE);
|
|
} else {
|
|
app.DebugPrintf(
|
|
"[NET] Warning: ServerStoppedWait() called but "
|
|
"m_hServerStoppedEvent is NULL\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void CGameNetworkManager::ServerStoppedDestroy() {
|
|
delete m_hServerStoppedEvent;
|
|
m_hServerStoppedEvent = NULL;
|
|
}
|
|
|
|
bool CGameNetworkManager::ServerStoppedValid() {
|
|
return (m_hServerStoppedEvent != NULL);
|
|
}
|
|
|
|
int CGameNetworkManager::GetJoiningReadyPercentage() {
|
|
return s_pPlatformNetworkManager->GetJoiningReadyPercentage();
|
|
}
|
|
|
|
#ifndef _XBOX
|
|
void CGameNetworkManager::FakeLocalPlayerJoined() {
|
|
s_pPlatformNetworkManager->FakeLocalPlayerJoined();
|
|
}
|
|
#endif
|
|
|
|
#ifdef __PSVITA__
|
|
bool CGameNetworkManager::usingAdhocMode() {
|
|
return ((CPlatformNetworkManagerSony*)s_pPlatformNetworkManager)
|
|
->usingAdhocMode();
|
|
}
|
|
|
|
void CGameNetworkManager::setAdhocMode(bool bAdhoc) {
|
|
((CPlatformNetworkManagerSony*)s_pPlatformNetworkManager)
|
|
->setAdhocMode(bAdhoc);
|
|
}
|
|
|
|
void CGameNetworkManager::startAdhocMatching() {
|
|
((CPlatformNetworkManagerSony*)s_pPlatformNetworkManager)
|
|
->startAdhocMatching();
|
|
}
|
|
|
|
#endif
|