4jcraft/Minecraft.Client/Platform/Common/UI/UIScene_JoinMenu.cpp
2026-03-23 18:53:18 +11:00

609 lines
22 KiB
C++

#include "../../Minecraft.World/Platform/stdafx.h"
#include "UI.h"
#include "UIScene_JoinMenu.h"
#include "../../Minecraft.Client/Minecraft.h"
#include "../../Minecraft.Client/Textures/Packs/TexturePackRepository.h"
#include "../../Minecraft.Client/GameState/Options.h"
#include "../../Minecraft.Client/MinecraftServer.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.h"
#define UPDATE_PLAYERS_TIMER_ID 0
#define UPDATE_PLAYERS_TIMER_TIME 30000
UIScene_JoinMenu::UIScene_JoinMenu(int iPad, void* _initData,
UILayer* parentLayer)
: UIScene(iPad, parentLayer) {
// Setup all the Iggy references we need for this scene
initialiseMovie();
JoinMenuInitData* initData = (JoinMenuInitData*)_initData;
m_selectedSession = initData->selectedSession;
m_friendInfoUpdatedOK = false;
m_friendInfoUpdatedERROR = false;
m_friendInfoRequestIssued = false;
}
void UIScene_JoinMenu::updateTooltips() {
int iA = -1;
int iY = -1;
if (getControlFocus() == eControl_GamePlayers) {
#ifdef _DURANGO
iY = IDS_TOOLTIPS_VIEW_GAMERCARD;
#endif
} else {
iA = IDS_TOOLTIPS_SELECT;
}
ui.SetTooltips(DEFAULT_XUI_MENU_USER, iA, IDS_TOOLTIPS_BACK, -1, iY);
}
void UIScene_JoinMenu::tick() {
if (!m_friendInfoRequestIssued) {
ui.NavigateToScene(m_iPad, eUIScene_Timer);
g_NetworkManager.GetFullFriendSessionInfo(m_selectedSession,
&friendSessionUpdated, this);
m_friendInfoRequestIssued = true;
}
if (m_friendInfoUpdatedOK) {
m_friendInfoUpdatedOK = false;
m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME), eControl_JoinGame);
m_buttonListPlayers.init(eControl_GamePlayers);
#if defined(__PS3__) || defined(__ORBIS__) || defined __PSVITA__
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++) {
if (m_selectedSession->data.players[i] != NULL) {
#ifndef _CONTENT_PACKAGE
if (app.DebugSettingsOn() &&
(app.GetGameSettingsDebugMask() &
(1L << eDebugSetting_DebugLeaderboards))) {
m_buttonListPlayers.addItem(L"WWWWWWWWWWWWWWWW");
} else
#endif
{
std::string playerName(
m_selectedSession->data.players[i].getOnlineID());
#ifndef __PSVITA__
// Append guest number (any players in an online game not
// signed into PSN are guests)
if (m_selectedSession->data.players[i].isSignedIntoPSN() ==
false) {
char suffix[5];
sprintf(
suffix, " (%d)",
m_selectedSession->data.players[i].getQuadrant() +
1);
playerName.append(suffix);
}
#endif
m_buttonListPlayers.addItem(playerName);
}
} else {
// Leave the loop when we hit the first NULL player
break;
}
}
#elif defined(_DURANGO)
for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++) {
if (m_selectedSession->searchResult.m_playerNames[i].size()) {
m_buttonListPlayers.addItem(
m_selectedSession->searchResult.m_playerNames[i]);
} else {
// Leave the loop when we hit the first empty player name
break;
}
}
#endif
m_labelLabels[eLabel_Difficulty].init(
app.GetString(IDS_LABEL_DIFFICULTY));
m_labelLabels[eLabel_GameType].init(app.GetString(IDS_LABEL_GAME_TYPE));
m_labelLabels[eLabel_GamertagsOn].init(
app.GetString(IDS_LABEL_GAMERTAGS));
m_labelLabels[eLabel_Structures].init(
app.GetString(IDS_LABEL_STRUCTURES));
m_labelLabels[eLabel_LevelType].init(
app.GetString(IDS_LABEL_LEVEL_TYPE));
m_labelLabels[eLabel_PVP].init(app.GetString(IDS_LABEL_PvP));
m_labelLabels[eLabel_Trust].init(app.GetString(IDS_LABEL_TRUST));
m_labelLabels[eLabel_TNTOn].init(app.GetString(IDS_LABEL_TNT));
m_labelLabels[eLabel_FireOn].init(
app.GetString(IDS_LABEL_FIRE_SPREADS));
unsigned int uiGameHostSettings =
m_selectedSession->data.m_uiGameHostSettings;
switch (app.GetGameHostOption(uiGameHostSettings,
eGameHostOption_Difficulty)) {
case Difficulty::EASY:
m_labelValues[eLabel_Difficulty].init(
app.GetString(IDS_DIFFICULTY_TITLE_EASY));
break;
case Difficulty::NORMAL:
m_labelValues[eLabel_Difficulty].init(
app.GetString(IDS_DIFFICULTY_TITLE_NORMAL));
break;
case Difficulty::HARD:
m_labelValues[eLabel_Difficulty].init(
app.GetString(IDS_DIFFICULTY_TITLE_HARD));
break;
case Difficulty::PEACEFUL:
default:
m_labelValues[eLabel_Difficulty].init(
app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL));
break;
}
int option =
app.GetGameHostOption(uiGameHostSettings, eGameHostOption_GameType);
if (option == GameType::CREATIVE->getId()) {
m_labelValues[eLabel_GameType].init(app.GetString(IDS_CREATIVE));
} else if (option == GameType::ADVENTURE->getId()) {
m_labelValues[eLabel_GameType].init(app.GetString(IDS_ADVENTURE));
} else {
m_labelValues[eLabel_GameType].init(app.GetString(IDS_SURVIVAL));
}
if (app.GetGameHostOption(uiGameHostSettings,
eGameHostOption_Gamertags))
m_labelValues[eLabel_GamertagsOn].init(app.GetString(IDS_ON));
else
m_labelValues[eLabel_GamertagsOn].init(app.GetString(IDS_OFF));
if (app.GetGameHostOption(uiGameHostSettings,
eGameHostOption_Structures))
m_labelValues[eLabel_Structures].init(app.GetString(IDS_ON));
else
m_labelValues[eLabel_Structures].init(app.GetString(IDS_OFF));
if (app.GetGameHostOption(uiGameHostSettings,
eGameHostOption_LevelType))
m_labelValues[eLabel_LevelType].init(
app.GetString(IDS_LEVELTYPE_SUPERFLAT));
else
m_labelValues[eLabel_LevelType].init(
app.GetString(IDS_LEVELTYPE_NORMAL));
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_PvP))
m_labelValues[eLabel_PVP].init(app.GetString(IDS_ON));
else
m_labelValues[eLabel_PVP].init(app.GetString(IDS_OFF));
if (app.GetGameHostOption(uiGameHostSettings,
eGameHostOption_TrustPlayers))
m_labelValues[eLabel_Trust].init(app.GetString(IDS_ON));
else
m_labelValues[eLabel_Trust].init(app.GetString(IDS_OFF));
if (app.GetGameHostOption(uiGameHostSettings, eGameHostOption_TNT))
m_labelValues[eLabel_TNTOn].init(app.GetString(IDS_ON));
else
m_labelValues[eLabel_TNTOn].init(app.GetString(IDS_OFF));
if (app.GetGameHostOption(uiGameHostSettings,
eGameHostOption_FireSpreads))
m_labelValues[eLabel_FireOn].init(app.GetString(IDS_ON));
else
m_labelValues[eLabel_FireOn].init(app.GetString(IDS_OFF));
m_bIgnoreInput = false;
// Alert the app the we want to be informed of ethernet connections
app.SetLiveLinkRequired(true);
TelemetryManager->RecordMenuShown(m_iPad, eUIScene_JoinMenu, 0);
addTimer(UPDATE_PLAYERS_TIMER_ID, UPDATE_PLAYERS_TIMER_TIME);
}
if (m_friendInfoUpdatedERROR) {
m_buttonJoinGame.init(app.GetString(IDS_JOIN_GAME), eControl_JoinGame);
m_buttonListPlayers.init(eControl_GamePlayers);
m_labelLabels[eLabel_Difficulty].init(
app.GetString(IDS_LABEL_DIFFICULTY));
m_labelLabels[eLabel_GameType].init(app.GetString(IDS_LABEL_GAME_TYPE));
m_labelLabels[eLabel_GamertagsOn].init(
app.GetString(IDS_LABEL_GAMERTAGS));
m_labelLabels[eLabel_Structures].init(
app.GetString(IDS_LABEL_STRUCTURES));
m_labelLabels[eLabel_LevelType].init(
app.GetString(IDS_LABEL_LEVEL_TYPE));
m_labelLabels[eLabel_PVP].init(app.GetString(IDS_LABEL_PvP));
m_labelLabels[eLabel_Trust].init(app.GetString(IDS_LABEL_TRUST));
m_labelLabels[eLabel_TNTOn].init(app.GetString(IDS_LABEL_TNT));
m_labelLabels[eLabel_FireOn].init(
app.GetString(IDS_LABEL_FIRE_SPREADS));
m_labelValues[eLabel_Difficulty].init(
app.GetString(IDS_DIFFICULTY_TITLE_PEACEFUL));
m_labelValues[eLabel_GameType].init(app.GetString(IDS_CREATIVE));
m_labelValues[eLabel_GamertagsOn].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_Structures].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_LevelType].init(
app.GetString(IDS_LEVELTYPE_NORMAL));
m_labelValues[eLabel_PVP].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_Trust].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_TNTOn].init(app.GetString(IDS_OFF));
m_labelValues[eLabel_FireOn].init(app.GetString(IDS_OFF));
m_friendInfoUpdatedERROR = false;
// Show a generic network error message, not always safe to assume the
// error was host quitting without bubbling more info up from the
// network manager so this is the best we can do
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
#ifdef _XBOX_ONE
ui.RequestErrorMessage(IDS_CONNECTION_FAILED,
IDS_DISCONNECTED_SERVER_QUIT, uiIDA, 1, m_iPad,
ErrorDialogReturned, this);
#else
ui.RequestErrorMessage(IDS_ERROR_NETWORK_TITLE, IDS_ERROR_NETWORK,
uiIDA, 1, m_iPad, ErrorDialogReturned, this);
#endif
}
UIScene::tick();
}
void UIScene_JoinMenu::friendSessionUpdated(bool success, void* pParam) {
UIScene_JoinMenu* scene = (UIScene_JoinMenu*)pParam;
ui.NavigateBack(scene->m_iPad);
if (success) {
scene->m_friendInfoUpdatedOK = true;
} else {
scene->m_friendInfoUpdatedERROR = true;
}
}
int UIScene_JoinMenu::ErrorDialogReturned(void* pParam, int iPad,
const C4JStorage::EMessageResult) {
UIScene_JoinMenu* scene = (UIScene_JoinMenu*)pParam;
ui.NavigateBack(scene->m_iPad);
return 0;
}
void UIScene_JoinMenu::updateComponents() {
m_parentLayer->showComponent(m_iPad, eUIComponent_Panorama, true);
m_parentLayer->showComponent(m_iPad, eUIComponent_Logo, true);
}
std::wstring UIScene_JoinMenu::getMoviePath() { return L"JoinMenu"; }
void UIScene_JoinMenu::handleInput(int iPad, int key, bool repeat, bool pressed,
bool released, bool& handled) {
if (m_bIgnoreInput) return;
ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released);
switch (key) {
case ACTION_MENU_CANCEL:
if (pressed) {
navigateBack();
handled = true;
}
break;
#ifdef _DURANGO
case ACTION_MENU_Y:
if (m_selectedSession != NULL &&
getControlFocus() == eControl_GamePlayers &&
m_buttonListPlayers.getItemCount() > 0) {
PlayerUID uid = m_selectedSession->searchResult.m_playerXuids
[m_buttonListPlayers.getCurrentSelection()];
if (uid != INVALID_XUID)
ProfileManager.ShowProfileCard(
ProfileManager.GetLockedProfile(), uid);
}
break;
#endif
case ACTION_MENU_OK:
if (getControlFocus() != eControl_GamePlayers) {
sendInputToMovie(key, repeat, pressed, released);
}
handled = true;
break;
#ifdef __ORBIS__
case ACTION_MENU_TOUCHPAD_PRESS:
#endif
case ACTION_MENU_UP:
case ACTION_MENU_DOWN:
case ACTION_MENU_PAGEUP:
case ACTION_MENU_PAGEDOWN:
sendInputToMovie(key, repeat, pressed, released);
handled = true;
break;
}
}
void UIScene_JoinMenu::handlePress(F64 controlId, F64 childId) {
switch ((int)controlId) {
case eControl_JoinGame: {
m_bIgnoreInput = true;
// CD - Added for audio
ui.PlayUISFX(eSFX_Press);
#ifdef _DURANGO
ProfileManager.CheckMultiplayerPrivileges(
m_iPad, true, &checkPrivilegeCallback, this);
#else
StartSharedLaunchFlow();
#endif
} break;
case eControl_GamePlayers:
break;
};
}
void UIScene_JoinMenu::handleFocusChange(F64 controlId, F64 childId) {
switch ((int)controlId) {
case eControl_GamePlayers:
m_buttonListPlayers.updateChildFocus((int)childId);
};
updateTooltips();
}
#ifdef _DURANGO
void UIScene_JoinMenu::checkPrivilegeCallback(void* lpParam, bool hasPrivilege,
int iPad) {
UIScene_JoinMenu* pClass = (UIScene_JoinMenu*)lpParam;
pClass->m_bIgnoreInput = false;
if (pClass) {
if (hasPrivilege) {
pClass->StartSharedLaunchFlow();
} else {
pClass->m_bIgnoreInput = false;
}
}
}
#endif
void UIScene_JoinMenu::StartSharedLaunchFlow() {
if (!app.IsLocalMultiplayerAvailable()) {
JoinGame(this);
} else {
// ProfileManager.RequestSignInUI(false, false, false, true,
// false,&UIScene_JoinMenu::StartGame_SignInReturned,
// this,ProfileManager.GetPrimaryPad());
SignInInfo info;
info.Func = &UIScene_JoinMenu::StartGame_SignInReturned;
info.lpParam = this;
info.requireOnline = true;
ui.NavigateToScene(ProfileManager.GetPrimaryPad(),
eUIScene_QuadrantSignin, &info);
}
}
int UIScene_JoinMenu::StartGame_SignInReturned(void* pParam, bool bContinue,
int iPad) {
UIScene_JoinMenu* pClass = (UIScene_JoinMenu*)ui.GetSceneFromCallbackId(
reinterpret_cast<size_t>(pParam));
if (pClass == NULL) {
pClass = (UIScene_JoinMenu*)pParam;
}
if (bContinue == true && pClass != NULL &&
ProfileManager.IsSignedIn(iPad)) {
JoinGame(pClass);
}
if (pClass != NULL) {
pClass->m_bIgnoreInput = false;
}
return 0;
}
// Shared function to join the game that is the same whether we used the
// sign-in UI or not
void UIScene_JoinMenu::JoinGame(UIScene_JoinMenu* pClass) {
bool noPrivileges = false;
int signedInUsers = 0;
int localUsersMask = 0;
DWORD dwLocalUsersMask = 0;
bool isSignedInLive = true;
int iPadNotSignedInLive = -1;
ProfileManager.SetLockedProfile(0); // TEMP!
// If we're in SD mode, then only the primary player gets to play
if (app.IsLocalMultiplayerAvailable()) {
for (unsigned int index = 0; index < XUSER_MAX_COUNT; ++index) {
if (ProfileManager.IsSignedIn(index)) {
if (isSignedInLive && !ProfileManager.IsSignedInLive(index)) {
// Record the first non signed in live pad
iPadNotSignedInLive = index;
}
if (!ProfileManager.AllowedToPlayMultiplayer(index))
noPrivileges = true;
dwLocalUsersMask |=
CGameNetworkManager::GetLocalPlayerMask(index);
isSignedInLive =
isSignedInLive && ProfileManager.IsSignedInLive(index);
}
}
} else {
if (ProfileManager.IsSignedIn(ProfileManager.GetPrimaryPad())) {
if (!ProfileManager.AllowedToPlayMultiplayer(
ProfileManager.GetPrimaryPad()))
noPrivileges = true;
dwLocalUsersMask |= CGameNetworkManager::GetLocalPlayerMask(
ProfileManager.GetPrimaryPad());
isSignedInLive =
ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad());
#ifdef __PSVITA__
if (CGameNetworkManager::usingAdhocMode() &&
SQRNetworkManager_AdHoc_Vita::GetAdhocStatus())
isSignedInLive = true;
#endif
}
}
// If this is an online game but not all players are signed in to Live,
// stop!
if (!isSignedInLive) {
#ifdef __ORBIS__
// Check if PSN is unavailable because of age restriction
int npAvailability =
ProfileManager.getNPAvailability(iPadNotSignedInLive);
if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) {
pClass->m_bIgnoreInput = false;
// 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
#endif
{
pClass->m_bIgnoreInput = false;
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_PRO_NOTONLINE_TITLE,
IDS_PRO_NOTONLINE_TEXT, uiIDA, 1,
ProfileManager.GetPrimaryPad());
}
return;
}
// Check if user-created content is allowed, as we cannot play
// multiplayer if it's not
bool noUGC = false;
bool pccAllowed = true;
bool pccFriendsAllowed = true;
#if defined(__PS3__) || defined(__PSVITA__)
if (isSignedInLive) {
ProfileManager.GetChatAndContentRestrictions(
ProfileManager.GetPrimaryPad(), false, &noUGC, NULL, NULL);
}
#else
ProfileManager.AllowedPlayerCreatedContent(
ProfileManager.GetPrimaryPad(), false, &pccAllowed, &pccFriendsAllowed);
if (!pccAllowed && !pccFriendsAllowed) noUGC = true;
#endif
#ifdef __PSVITA__
if (CGameNetworkManager::usingAdhocMode()) {
noPrivileges = false;
noUGC = false;
}
#endif
if (noUGC) {
pClass->setVisible(true);
pClass->m_bIgnoreInput = false;
int messageText = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_SINGLE_LOCAL;
if (signedInUsers > 1)
messageText = IDS_NO_USER_CREATED_CONTENT_PRIVILEGE_ALL_LOCAL;
ui.RequestUGCMessageBox(IDS_CONNECTION_FAILED, messageText);
} else if (noPrivileges) {
pClass->setVisible(true);
pClass->m_bIgnoreInput = false;
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(
ProfileManager.GetPrimaryPad(), false, &chatRestricted, NULL, NULL);
if (chatRestricted) {
ProfileManager.DisplaySystemMessage(
SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION,
ProfileManager.GetPrimaryPad());
}
#endif
CGameNetworkManager::eJoinGameResult result = g_NetworkManager.JoinGame(
pClass->m_selectedSession, dwLocalUsersMask);
// Alert the app the we no longer want to be informed of ethernet
// connections
app.SetLiveLinkRequired(false);
if (result != CGameNetworkManager::JOINGAME_SUCCESS) {
int exitReasonStringId = -1;
switch (result) {
case CGameNetworkManager::JOINGAME_FAIL_SERVER_FULL:
exitReasonStringId = IDS_DISCONNECTED_SERVER_FULL;
break;
default:
break;
}
if (exitReasonStringId == -1) {
ui.NavigateBack(pClass->m_iPad);
} else {
unsigned int uiIDA[1];
uiIDA[0] = IDS_CONFIRM_OK;
ui.RequestErrorMessage(IDS_CONNECTION_FAILED,
exitReasonStringId, uiIDA, 1,
ProfileManager.GetPrimaryPad());
exitReasonStringId = -1;
ui.NavigateToHomeMenu();
}
}
}
}
void UIScene_JoinMenu::handleTimerComplete(int id) {
switch (id) {
case UPDATE_PLAYERS_TIMER_ID: {
#if TO_BE_IMPLEMENTED
PlayerUID selectedPlayerXUID =
m_selectedSession->data.players[playersList.GetCurSel()];
bool success = g_NetworkManager.GetGameSessionInfo(
m_iPad, m_selectedSession->sessionId, m_selectedSession);
if (success) {
playersList.DeleteItems(0, playersList.GetItemCount());
int selectedIndex = 0;
for (unsigned int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; ++i) {
if (m_selectedSession->data.players[i] != NULL) {
if (m_selectedSession->data.players[i] ==
selectedPlayerXUID)
selectedIndex = i;
playersList.InsertItems(i, 1);
#ifndef _CONTENT_PACKAGE
if (app.DebugSettingsOn() &&
(app.GetGameSettingsDebugMask() &
(1L << eDebugSetting_DebugLeaderboards))) {
playersList.SetText(i, L"WWWWWWWWWWWWWWWW");
} else
#endif
{
playersList.SetText(
i, convStringToWstring(
m_selectedSession->data.szPlayers[i])
.c_str());
}
} else {
// Leave the loop when we hit the first NULL player
break;
}
}
playersList.SetCurSel(selectedIndex);
}
#endif
} break;
};
}