mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-04-24 01:24:07 +00:00
513 lines
20 KiB
C++
513 lines
20 KiB
C++
#include "app/common/NetworkController.h"
|
|
|
|
#include <chrono>
|
|
#include <cstring>
|
|
#include <thread>
|
|
|
|
#include "app/common/Game.h"
|
|
#include "app/common/Network/GameNetworkManager.h"
|
|
#include "app/linux/LinuxGame.h"
|
|
#include "app/linux/Linux_UIController.h"
|
|
#include "minecraft/client/Minecraft.h"
|
|
#include "minecraft/client/ProgressRenderer.h"
|
|
#include "minecraft/client/multiplayer/MultiPlayerLevel.h"
|
|
#include "minecraft/client/multiplayer/MultiPlayerLocalPlayer.h"
|
|
#include "minecraft/client/renderer/GameRenderer.h"
|
|
#include "minecraft/client/skins/DLCTexturePack.h"
|
|
#include "minecraft/client/skins/TexturePack.h"
|
|
#include "minecraft/client/skins/TexturePackRepository.h"
|
|
#include "minecraft/server/MinecraftServer.h"
|
|
#include "minecraft/world/level/storage/ConsoleSaveFileIO/compression.h"
|
|
#include "platform/input/input.h"
|
|
#include "platform/profile/profile.h"
|
|
#include "platform/storage/storage.h"
|
|
|
|
unsigned int NetworkController::m_uiLastSignInData = 0;
|
|
|
|
NetworkController::NetworkController() {
|
|
m_disconnectReason = DisconnectPacket::eDisconnect_None;
|
|
m_bLiveLinkRequired = false;
|
|
m_bChangingSessionType = false;
|
|
m_bReallyChangingSessionType = false;
|
|
|
|
memset(&m_InviteData, 0, sizeof(JoinFromInviteData));
|
|
memset(m_playerColours, 0, MINECRAFT_NET_MAX_PLAYERS);
|
|
memset(m_playerGamePrivileges, 0, sizeof(m_playerGamePrivileges));
|
|
|
|
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
|
|
if (XUserGetSigninInfo(i, XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY,
|
|
&m_currentSigninInfo[i]) < 0) {
|
|
m_currentSigninInfo[i].xuid = INVALID_XUID;
|
|
m_currentSigninInfo[i].dwGuestNumber = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void NetworkController::updatePlayerInfo(std::uint8_t networkSmallId,
|
|
int16_t playerColourIndex,
|
|
unsigned int playerGamePrivileges) {
|
|
for (unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) {
|
|
if (m_playerColours[i] == networkSmallId) {
|
|
m_playerColours[i] = 0;
|
|
m_playerGamePrivileges[i] = 0;
|
|
}
|
|
}
|
|
if (playerColourIndex >= 0 &&
|
|
playerColourIndex < MINECRAFT_NET_MAX_PLAYERS) {
|
|
m_playerColours[playerColourIndex] = networkSmallId;
|
|
m_playerGamePrivileges[playerColourIndex] = playerGamePrivileges;
|
|
}
|
|
}
|
|
|
|
short NetworkController::getPlayerColour(std::uint8_t networkSmallId) {
|
|
short index = -1;
|
|
for (unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) {
|
|
if (m_playerColours[i] == networkSmallId) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
return index;
|
|
}
|
|
|
|
unsigned int NetworkController::getPlayerPrivileges(
|
|
std::uint8_t networkSmallId) {
|
|
unsigned int privileges = 0;
|
|
for (unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) {
|
|
if (m_playerColours[i] == networkSmallId) {
|
|
privileges = m_playerGamePrivileges[i];
|
|
break;
|
|
}
|
|
}
|
|
return privileges;
|
|
}
|
|
|
|
void NetworkController::processInvite(std::uint32_t dwUserIndex,
|
|
std::uint32_t dwLocalUsersMask,
|
|
const INVITE_INFO* pInviteInfo) {
|
|
m_InviteData.dwUserIndex = dwUserIndex;
|
|
m_InviteData.dwLocalUsersMask = dwLocalUsersMask;
|
|
m_InviteData.pInviteInfo = pInviteInfo;
|
|
app.SetAction(dwUserIndex, eAppAction_ExitAndJoinFromInvite);
|
|
}
|
|
|
|
int NetworkController::primaryPlayerSignedOutReturned(
|
|
void* pParam, int iPad, const IPlatformStorage::EMessageResult) {
|
|
if (g_NetworkManager.IsInSession()) {
|
|
app.SetAction(iPad, eAppAction_PrimaryPlayerSignedOutReturned);
|
|
} else {
|
|
app.SetAction(iPad, eAppAction_PrimaryPlayerSignedOutReturned_Menus);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int NetworkController::ethernetDisconnectReturned(
|
|
void* pParam, int iPad, const IPlatformStorage::EMessageResult) {
|
|
Minecraft* pMinecraft = Minecraft::GetInstance();
|
|
|
|
if (Minecraft::GetInstance()->player != nullptr) {
|
|
app.SetAction(pMinecraft->player->GetXboxPad(),
|
|
eAppAction_EthernetDisconnectedReturned);
|
|
} else {
|
|
app.SetAction(iPad, eAppAction_EthernetDisconnectedReturned_Menus);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void NetworkController::profileReadErrorCallback(void* pParam) {
|
|
Game* pApp = (Game*)pParam;
|
|
int iPrimaryPlayer = PlatformProfile.GetPrimaryPad();
|
|
pApp->SetAction(iPrimaryPlayer, eAppAction_ProfileReadError);
|
|
}
|
|
|
|
int NetworkController::signoutExitWorldThreadProc(void* lpParameter) {
|
|
Compression::UseDefaultThreadStorage();
|
|
|
|
Minecraft* pMinecraft = Minecraft::GetInstance();
|
|
|
|
int exitReasonStringId = -1;
|
|
|
|
bool saveStats = false;
|
|
if (pMinecraft->isClientSide() || g_NetworkManager.IsInSession()) {
|
|
if (lpParameter != nullptr) {
|
|
switch (app.GetDisconnectReason()) {
|
|
case DisconnectPacket::eDisconnect_Kicked:
|
|
exitReasonStringId = IDS_DISCONNECTED_KICKED;
|
|
break;
|
|
case DisconnectPacket::eDisconnect_NoUGC_AllLocal:
|
|
exitReasonStringId =
|
|
IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL;
|
|
break;
|
|
case DisconnectPacket::eDisconnect_NoUGC_Single_Local:
|
|
exitReasonStringId =
|
|
IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL;
|
|
break;
|
|
case DisconnectPacket::eDisconnect_NoFlying:
|
|
exitReasonStringId = IDS_DISCONNECTED_FLYING;
|
|
break;
|
|
case DisconnectPacket::eDisconnect_OutdatedServer:
|
|
exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD;
|
|
break;
|
|
case DisconnectPacket::eDisconnect_OutdatedClient:
|
|
exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD;
|
|
break;
|
|
default:
|
|
exitReasonStringId = IDS_DISCONNECTED;
|
|
}
|
|
pMinecraft->progressRenderer->progressStartNoAbort(
|
|
exitReasonStringId);
|
|
if (pMinecraft->levels[0] != nullptr)
|
|
pMinecraft->levels[0]->disconnect(false);
|
|
if (pMinecraft->levels[1] != nullptr)
|
|
pMinecraft->levels[1]->disconnect(false);
|
|
} else {
|
|
exitReasonStringId = IDS_EXITING_GAME;
|
|
pMinecraft->progressRenderer->progressStartNoAbort(
|
|
IDS_EXITING_GAME);
|
|
|
|
if (pMinecraft->levels[0] != nullptr)
|
|
pMinecraft->levels[0]->disconnect();
|
|
if (pMinecraft->levels[1] != nullptr)
|
|
pMinecraft->levels[1]->disconnect();
|
|
}
|
|
|
|
MinecraftServer::HaltServer(true);
|
|
saveStats = false;
|
|
g_NetworkManager.LeaveGame(false);
|
|
} else {
|
|
if (lpParameter != nullptr) {
|
|
switch (app.GetDisconnectReason()) {
|
|
case DisconnectPacket::eDisconnect_Kicked:
|
|
exitReasonStringId = IDS_DISCONNECTED_KICKED;
|
|
break;
|
|
case DisconnectPacket::eDisconnect_NoUGC_AllLocal:
|
|
exitReasonStringId =
|
|
IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL;
|
|
break;
|
|
case DisconnectPacket::eDisconnect_NoUGC_Single_Local:
|
|
exitReasonStringId =
|
|
IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL;
|
|
break;
|
|
case DisconnectPacket::eDisconnect_OutdatedServer:
|
|
exitReasonStringId = IDS_DISCONNECTED_SERVER_OLD;
|
|
break;
|
|
case DisconnectPacket::eDisconnect_OutdatedClient:
|
|
exitReasonStringId = IDS_DISCONNECTED_CLIENT_OLD;
|
|
default:
|
|
exitReasonStringId = IDS_DISCONNECTED;
|
|
}
|
|
pMinecraft->progressRenderer->progressStartNoAbort(
|
|
exitReasonStringId);
|
|
}
|
|
}
|
|
pMinecraft->setLevel(nullptr, exitReasonStringId, nullptr, saveStats, true);
|
|
|
|
app.m_gameRules.unloadCurrentGameRules();
|
|
|
|
MinecraftServer::resetFlags();
|
|
|
|
while (g_NetworkManager.IsInSession()) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void NetworkController::clearSignInChangeUsersMask() {
|
|
int iPrimaryPlayer = PlatformProfile.GetPrimaryPad();
|
|
|
|
if (m_uiLastSignInData != 0) {
|
|
if (iPrimaryPlayer >= 0) {
|
|
m_uiLastSignInData = 1 << iPrimaryPlayer;
|
|
} else {
|
|
m_uiLastSignInData = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void NetworkController::signInChangeCallback(void* pParam,
|
|
bool bPrimaryPlayerChanged,
|
|
unsigned int uiSignInData) {
|
|
Game* pApp = (Game*)pParam;
|
|
int iPrimaryPlayer = PlatformProfile.GetPrimaryPad();
|
|
|
|
if ((PlatformProfile.GetLockedProfile() != -1) && iPrimaryPlayer != -1) {
|
|
if (((uiSignInData & (1 << iPrimaryPlayer)) == 0) ||
|
|
bPrimaryPlayerChanged) {
|
|
pApp->SetAction(iPrimaryPlayer, eAppAction_PrimaryPlayerSignedOut);
|
|
pApp->InvalidateBannedList(iPrimaryPlayer);
|
|
PlatformStorage.ClearDLCOffers();
|
|
pApp->ClearAndResetDLCDownloadQueue();
|
|
pApp->ClearDLCInstalled();
|
|
} else {
|
|
unsigned int uiChangedPlayers = uiSignInData ^ m_uiLastSignInData;
|
|
|
|
if (g_NetworkManager.IsInSession()) {
|
|
bool hasGuestIdChanged = false;
|
|
for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) {
|
|
unsigned int guestNumber = 0;
|
|
if (PlatformProfile.IsSignedIn(i)) {
|
|
XUSER_SIGNIN_INFO info;
|
|
XUserGetSigninInfo(
|
|
i, XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY, &info);
|
|
pApp->DebugPrintf(
|
|
"Player at index %d has guest number %d\n", i,
|
|
info.dwGuestNumber);
|
|
guestNumber = info.dwGuestNumber;
|
|
}
|
|
if (pApp->m_networkController.m_currentSigninInfo[i]
|
|
.dwGuestNumber != 0 &&
|
|
guestNumber != 0 &&
|
|
pApp->m_networkController.m_currentSigninInfo[i]
|
|
.dwGuestNumber != guestNumber) {
|
|
hasGuestIdChanged = true;
|
|
}
|
|
}
|
|
|
|
if (hasGuestIdChanged) {
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0] = IDS_CONFIRM_OK;
|
|
ui.RequestErrorMessage(IDS_GUEST_ORDER_CHANGED_TITLE,
|
|
IDS_GUEST_ORDER_CHANGED_TEXT, uiIDA,
|
|
1, PlatformProfile.GetPrimaryPad());
|
|
}
|
|
|
|
bool switchToOffline = false;
|
|
if (!PlatformProfile.IsSignedInLive(
|
|
PlatformProfile.GetLockedProfile()) &&
|
|
!g_NetworkManager.IsLocalGame()) {
|
|
switchToOffline = true;
|
|
}
|
|
|
|
for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) {
|
|
if (i == iPrimaryPlayer) continue;
|
|
|
|
if (hasGuestIdChanged &&
|
|
pApp->m_networkController.m_currentSigninInfo[i]
|
|
.dwGuestNumber != 0 &&
|
|
g_NetworkManager.GetLocalPlayerByUserIndex(i) !=
|
|
nullptr) {
|
|
pApp->DebugPrintf(
|
|
"Recommending removal of player at index %d "
|
|
"because their guest id changed\n",
|
|
i);
|
|
pApp->SetAction(i, eAppAction_ExitPlayer);
|
|
} else {
|
|
XUSER_SIGNIN_INFO info;
|
|
XUserGetSigninInfo(
|
|
i, XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY, &info);
|
|
|
|
bool bPlayerChanged =
|
|
(uiChangedPlayers & (1 << i)) == (1 << i);
|
|
bool bPlayerSignedIn = ((uiSignInData & (1 << i)) != 0);
|
|
|
|
if (bPlayerChanged &&
|
|
(!bPlayerSignedIn ||
|
|
(bPlayerSignedIn && !PlatformProfile.AreXUIDSEqual(
|
|
pApp->m_networkController
|
|
.m_currentSigninInfo[i]
|
|
.xuid,
|
|
info.xuid)))) {
|
|
pApp->DebugPrintf(
|
|
"Player at index %d Left - invalidating their "
|
|
"banned list\n",
|
|
i);
|
|
pApp->InvalidateBannedList(i);
|
|
|
|
if (g_NetworkManager.GetLocalPlayerByUserIndex(i) !=
|
|
nullptr ||
|
|
Minecraft::GetInstance()->localplayers[i] !=
|
|
nullptr) {
|
|
pApp->DebugPrintf("Player %d signed out\n", i);
|
|
pApp->SetAction(i, eAppAction_ExitPlayer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (switchToOffline) {
|
|
pApp->SetAction(iPrimaryPlayer,
|
|
eAppAction_EthernetDisconnected);
|
|
}
|
|
|
|
g_NetworkManager.HandleSignInChange();
|
|
} else if (pApp->GetLiveLinkRequired() &&
|
|
!PlatformProfile.IsSignedInLive(
|
|
PlatformProfile.GetLockedProfile())) {
|
|
{
|
|
pApp->SetAction(iPrimaryPlayer,
|
|
eAppAction_EthernetDisconnected);
|
|
}
|
|
}
|
|
}
|
|
m_uiLastSignInData = uiSignInData;
|
|
} else if (iPrimaryPlayer != -1) {
|
|
pApp->InvalidateBannedList(iPrimaryPlayer);
|
|
PlatformStorage.ClearDLCOffers();
|
|
pApp->ClearAndResetDLCDownloadQueue();
|
|
pApp->ClearDLCInstalled();
|
|
}
|
|
|
|
for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) {
|
|
if (XUserGetSigninInfo(
|
|
i, XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY,
|
|
&pApp->m_networkController.m_currentSigninInfo[i]) < 0) {
|
|
pApp->m_networkController.m_currentSigninInfo[i].xuid =
|
|
INVALID_XUID;
|
|
pApp->m_networkController.m_currentSigninInfo[i].dwGuestNumber = 0;
|
|
}
|
|
app.DebugPrintf(
|
|
"Player at index %d has guest number %d\n", i,
|
|
pApp->m_networkController.m_currentSigninInfo[i].dwGuestNumber);
|
|
}
|
|
}
|
|
|
|
void NetworkController::notificationsCallback(void* pParam,
|
|
std::uint32_t dwNotification,
|
|
unsigned int uiParam) {
|
|
Game* pClass = (Game*)pParam;
|
|
|
|
PNOTIFICATION pNotification = new NOTIFICATION;
|
|
pNotification->dwNotification = dwNotification;
|
|
pNotification->uiParam = uiParam;
|
|
|
|
switch (dwNotification) {
|
|
case XN_SYS_SIGNINCHANGED: {
|
|
pClass->DebugPrintf("Signing changed - %d\n", uiParam);
|
|
} break;
|
|
case XN_SYS_INPUTDEVICESCHANGED:
|
|
if (app.GetGameStarted() && g_NetworkManager.IsInSession()) {
|
|
for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) {
|
|
if (!PlatformInput.IsPadConnected(i) &&
|
|
Minecraft::GetInstance()->localplayers[i] != nullptr &&
|
|
!ui.IsPauseMenuDisplayed(i) &&
|
|
!ui.IsSceneInStack(i, eUIScene_EndPoem)) {
|
|
ui.CloseUIScenes(i);
|
|
ui.NavigateToScene(i, eUIScene_PauseMenu);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case XN_LIVE_CONTENT_INSTALLED: {
|
|
app.ClearDLCInstalled();
|
|
ui.HandleDLCInstalled(PlatformProfile.GetPrimaryPad());
|
|
} break;
|
|
case XN_SYS_STORAGEDEVICESCHANGED: {
|
|
} break;
|
|
}
|
|
|
|
pClass->m_networkController.m_vNotifications.push_back(pNotification);
|
|
}
|
|
|
|
void NetworkController::liveLinkChangeCallback(void* pParam, bool bConnected) {
|
|
// Implementation is platform-specific, stub here
|
|
}
|
|
|
|
int NetworkController::exitAndJoinFromInvite(
|
|
void* pParam, int iPad, IPlatformStorage::EMessageResult result) {
|
|
Game* pApp = (Game*)pParam;
|
|
|
|
if (result == IPlatformStorage::EMessage_ResultDecline) {
|
|
pApp->SetAction(iPad, eAppAction_ExitAndJoinFromInviteConfirmed);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int NetworkController::exitAndJoinFromInviteSaveDialogReturned(
|
|
void* pParam, int iPad, IPlatformStorage::EMessageResult result) {
|
|
Game* pClass = (Game*)pParam;
|
|
if (result == IPlatformStorage::EMessage_ResultDecline ||
|
|
result == IPlatformStorage::EMessage_ResultThirdOption) {
|
|
if (result == IPlatformStorage::EMessage_ResultDecline) {
|
|
if (!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) {
|
|
TexturePack* tPack =
|
|
Minecraft::GetInstance()->skins->getSelected();
|
|
DLCPack* pDLCPack = tPack->getDLCPack();
|
|
if (!pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Texture,
|
|
"")) {
|
|
unsigned int uiIDA[2];
|
|
uiIDA[0] = IDS_CONFIRM_OK;
|
|
uiIDA[1] = IDS_CONFIRM_CANCEL;
|
|
|
|
ui.RequestErrorMessage(
|
|
IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE,
|
|
IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad,
|
|
&NetworkController::warningTrialTexturePackReturned,
|
|
pClass);
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
bool bSaveExists;
|
|
PlatformStorage.DoesSaveExist(&bSaveExists);
|
|
if (bSaveExists) {
|
|
unsigned int uiIDA[2];
|
|
uiIDA[0] = IDS_CONFIRM_CANCEL;
|
|
uiIDA[1] = IDS_CONFIRM_OK;
|
|
ui.RequestErrorMessage(
|
|
IDS_TITLE_SAVE_GAME, IDS_CONFIRM_SAVE_GAME, uiIDA, 2,
|
|
PlatformProfile.GetPrimaryPad(),
|
|
&NetworkController::exitAndJoinFromInviteAndSaveReturned,
|
|
pClass);
|
|
return 0;
|
|
} else {
|
|
MinecraftServer::getInstance()->setSaveOnExit(true);
|
|
}
|
|
} else {
|
|
unsigned int uiIDA[2];
|
|
uiIDA[0] = IDS_CONFIRM_CANCEL;
|
|
uiIDA[1] = IDS_CONFIRM_OK;
|
|
ui.RequestErrorMessage(
|
|
IDS_TITLE_DECLINE_SAVE_GAME, IDS_CONFIRM_DECLINE_SAVE_GAME,
|
|
uiIDA, 2, PlatformProfile.GetPrimaryPad(),
|
|
&NetworkController::exitAndJoinFromInviteDeclineSaveReturned,
|
|
pClass);
|
|
return 0;
|
|
}
|
|
|
|
app.SetAction(PlatformProfile.GetPrimaryPad(),
|
|
eAppAction_ExitAndJoinFromInviteConfirmed);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int NetworkController::warningTrialTexturePackReturned(
|
|
void* pParam, int iPad, IPlatformStorage::EMessageResult result) {
|
|
return 0;
|
|
}
|
|
|
|
int NetworkController::exitAndJoinFromInviteAndSaveReturned(
|
|
void* pParam, int iPad, IPlatformStorage::EMessageResult result) {
|
|
if (result == IPlatformStorage::EMessage_ResultDecline) {
|
|
if (!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) {
|
|
TexturePack* tPack = Minecraft::GetInstance()->skins->getSelected();
|
|
DLCPack* pDLCPack = tPack->getDLCPack();
|
|
if (!pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Texture,
|
|
"")) {
|
|
unsigned int uiIDA[2];
|
|
uiIDA[0] = IDS_CONFIRM_OK;
|
|
uiIDA[1] = IDS_CONFIRM_CANCEL;
|
|
ui.RequestErrorMessage(
|
|
IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE,
|
|
IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad,
|
|
&NetworkController::warningTrialTexturePackReturned,
|
|
nullptr);
|
|
return 0;
|
|
}
|
|
}
|
|
MinecraftServer::getInstance()->setSaveOnExit(true);
|
|
app.SetAction(iPad, eAppAction_ExitAndJoinFromInviteConfirmed);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int NetworkController::exitAndJoinFromInviteDeclineSaveReturned(
|
|
void* pParam, int iPad, IPlatformStorage::EMessageResult result) {
|
|
if (result == IPlatformStorage::EMessage_ResultDecline) {
|
|
MinecraftServer::getInstance()->setSaveOnExit(false);
|
|
app.SetAction(iPad, eAppAction_ExitAndJoinFromInviteConfirmed);
|
|
}
|
|
return 0;
|
|
}
|