mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
The old Windows64 port had no real player identity — it used hardcoded fake XUIDs, so anyone could impersonate anyone. This replaces that with proper auth supporting Mojang, Ely.by, and offline accounts. MCAuth library (new, MCAuth/): Mojang auth via MSA device code flow (XBL, SISU, MC services), Ely.by via Yggdrasil with 2FA, offline UUID generation matching Java Edition (MD5 v3 from "OfflinePlayer:<name>"). Multi-account manager with background token refresh, per-slot sessions, and on-disk token persistence. Server-side session verification via Mojang/Ely.by hasJoined API. Skin fetching and PNG validation from texture servers. Network protocol (version bumped to 80): Three new packets (AuthScheme, AuthResponse, AuthResult) implement a server-driven auth handshake before login completes. Player identity migrated from 64-bit XUID to 128-bit GameUUID backed by two uint64 fields (hi/lo). readPlayerUID/writePlayerUID now serialize 16 bytes on the wire. Old and new clients cannot connect to each other — version mismatch is rejected at PreLogin. Save migration: Map data mappings auto-migrate from old format: the old 64-bit XUID is placed in hi, lo is set to 0 as a sentinel. On first access by the real player, the sentinel entry is upgraded in-place to the full 128-bit UUID. Format detection is by file size (2080, 2112, or 4160 bytes). Player .dat filenames inside saveData.ms change from decimal XUID to dashed UUID — old saves need manual entry renaming in the archive. UI: NativeUIRenderer: immediate-mode drawing system (quads, text, 9-slice panels, scrollbars, focus lists) for rendering auth screens without Flash/Scaleform. UIScene_MSAuth handles device code display, Ely.by credential input with 2FA, per-account skin head preview, and multi-account add/remove/switch. Server: online-mode and auth-provider (mojang/elyby) in server.properties. Whitelist and ban checks validate against the server-verified UUID. Incompatible auth scheme logs which provider the server expects vs what the client is using. Also fixes a pre-existing exploit where any client could send a DebugOptionsPacket to grant themselves CraftAnything and other debug privileges on any server — now requires OP status server-side.
336 lines
9.5 KiB
C++
336 lines
9.5 KiB
C++
#define _CRT_SECURE_NO_WARNINGS
|
|
#include "stdafx.h"
|
|
#include "UI.h"
|
|
#if defined(__PS3__) || defined(__ORBIS__)
|
|
#include "Common\Network\Sony\SonyCommerce.h"
|
|
#endif
|
|
#include "UIScene_DLCMainMenu.h"
|
|
#include "../../../MCAuth/include/MCAuthManager.h"
|
|
#include <cstdio>
|
|
#include <cstdarg>
|
|
|
|
#if !defined(_FINAL_BUILD) && defined(_DEBUG)
|
|
static void DLCMenuLog(const char* fmt, ...) {
|
|
char buf[512];
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
va_end(ap);
|
|
#ifdef _WIN32
|
|
OutputDebugStringA(buf);
|
|
#endif
|
|
}
|
|
#else
|
|
static void DLCMenuLog(const char* /*fmt*/, ...) {}
|
|
#endif
|
|
|
|
#define PLAYER_ONLINE_TIMER_ID 0
|
|
#define PLAYER_ONLINE_TIMER_TIME 100
|
|
|
|
UIScene_DLCMainMenu::UIScene_DLCMainMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer)
|
|
{
|
|
// Setup all the Iggy references we need for this scene
|
|
initialiseMovie();
|
|
// Alert the app the we want to be informed of ethernet connections
|
|
app.SetLiveLinkRequired( true );
|
|
|
|
m_labelOffers.init(IDS_DOWNLOADABLE_CONTENT_OFFERS);
|
|
m_buttonListOffers.init(eControl_OffersList);
|
|
|
|
#if defined _XBOX_ONE || defined __ORBIS__
|
|
// load any local DLC images
|
|
app.LoadLocalDLCImages();
|
|
#endif
|
|
|
|
#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
|
|
// show a timer on this menu
|
|
m_Timer.setVisible(true);
|
|
|
|
m_bCategoriesShown=false;
|
|
#endif
|
|
|
|
// Try to restore a previously saved Java auth session (background refresh).
|
|
MCAuthManager::Get().TryRestoreActiveJavaAccount();
|
|
DLCMenuLog("[DLCMainMenu] After TryRestore: IsJavaLoggedIn=%d, State=%d\n",
|
|
(int)MCAuthManager::Get().IsJavaLoggedIn(),
|
|
(int)MCAuthManager::Get().GetState());
|
|
|
|
// Pre-warm: proactively refresh token if it's expiring soon
|
|
if (MCAuthManager::Get().IsJavaLoggedIn() && MCAuthManager::Get().IsTokenExpiringSoon(0))
|
|
{
|
|
MCAuthManager::Get().RefreshSlot(0);
|
|
}
|
|
|
|
{
|
|
#ifdef _DURANGO
|
|
m_labelXboxStore.init(IDS_XBOX_STORE);
|
|
#else
|
|
m_labelXboxStore.init(L"");
|
|
#endif
|
|
// Show Minecraft username if already signed in, otherwise show generic label
|
|
if(MCAuthManager::Get().IsJavaLoggedIn())
|
|
{
|
|
MCAuth::JavaSession session = MCAuthManager::Get().GetJavaSession();
|
|
std::wstring name(session.username.begin(), session.username.end());
|
|
DLCMenuLog("[DLCMainMenu] Constructor: Already logged in as '%s'\n",
|
|
session.username.c_str());
|
|
m_labelXboxStore.init(name);
|
|
m_authLabelUpdated = true;
|
|
}
|
|
else
|
|
{
|
|
m_labelXboxStore.init(L"Sign in with Microsoft");
|
|
}
|
|
}
|
|
|
|
#if defined(_DURANGO)
|
|
m_Timer.setVisible(false);
|
|
|
|
m_buttonListOffers.addItem(IDS_DLC_MENU_SKINPACKS,e_DLC_SkinPack);
|
|
m_buttonListOffers.addItem(IDS_DLC_MENU_TEXTUREPACKS,e_DLC_TexturePacks);
|
|
m_buttonListOffers.addItem(IDS_DLC_MENU_MASHUPPACKS,e_DLC_MashupPacks);
|
|
|
|
app.AddDLCRequest(e_Marketplace_Content); // content is skin packs, texture packs and mash-up packs
|
|
// we also need to mount the local DLC so we can tell what's been purchased
|
|
app.StartInstallDLCProcess(iPad);
|
|
#endif
|
|
|
|
TelemetryManager->RecordMenuShown(iPad, eUIScene_DLCMainMenu, 0);
|
|
|
|
#if defined __ORBIS__ || defined __PSVITA__
|
|
app.GetCommerce()->ShowPsStoreIcon();
|
|
#endif
|
|
|
|
#if ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ )
|
|
addTimer( PLAYER_ONLINE_TIMER_ID, PLAYER_ONLINE_TIMER_TIME );
|
|
#endif
|
|
}
|
|
|
|
UIScene_DLCMainMenu::~UIScene_DLCMainMenu()
|
|
{
|
|
// Alert the app the we no longer want to be informed of ethernet connections
|
|
app.SetLiveLinkRequired( false );
|
|
#if defined _XBOX_ONE || defined __ORBIS__
|
|
app.FreeLocalDLCImages();
|
|
#endif
|
|
|
|
#ifdef _XBOX_ONE
|
|
// 4J-JEV: Have to switch back to user preferred languge now.
|
|
setLanguageOverride(true);
|
|
#endif
|
|
}
|
|
|
|
wstring UIScene_DLCMainMenu::getMoviePath()
|
|
{
|
|
return L"DLCMainMenu";
|
|
}
|
|
|
|
void UIScene_DLCMainMenu::updateTooltips()
|
|
{
|
|
ui.SetTooltips( m_iPad, IDS_TOOLTIPS_SELECT, IDS_TOOLTIPS_BACK );
|
|
}
|
|
|
|
void UIScene_DLCMainMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
|
|
{
|
|
//app.DebugPrintf("UIScene_DebugOverlay handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE");
|
|
ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released);
|
|
|
|
switch(key)
|
|
{
|
|
case ACTION_MENU_CANCEL:
|
|
if(pressed)
|
|
{
|
|
#if defined __ORBIS__ || defined __PSVITA__
|
|
app.GetCommerce()->HidePsStoreIcon();
|
|
#endif
|
|
navigateBack();
|
|
}
|
|
break;
|
|
case ACTION_MENU_OK:
|
|
#ifdef __ORBIS__
|
|
case ACTION_MENU_TOUCHPAD_PRESS:
|
|
#endif
|
|
sendInputToMovie(key, repeat, pressed, released);
|
|
break;
|
|
case ACTION_MENU_UP:
|
|
case ACTION_MENU_DOWN:
|
|
case ACTION_MENU_LEFT:
|
|
case ACTION_MENU_RIGHT:
|
|
case ACTION_MENU_PAGEUP:
|
|
case ACTION_MENU_PAGEDOWN:
|
|
sendInputToMovie(key, repeat, pressed, released);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void UIScene_DLCMainMenu::handlePress(F64 controlId, F64 childId)
|
|
{
|
|
switch(static_cast<int>(controlId))
|
|
{
|
|
case eControl_OffersList:
|
|
{
|
|
int iIndex = static_cast<int>(childId);
|
|
DLCOffersParam *param = new DLCOffersParam();
|
|
param->iPad = m_iPad;
|
|
|
|
param->iType = iIndex;
|
|
// promote the DLC content request type
|
|
|
|
// Xbox One will have requested the marketplace content - there is only that type
|
|
#ifndef _XBOX_ONE
|
|
app.AddDLCRequest(static_cast<eDLCMarketplaceType>(iIndex), true);
|
|
#endif
|
|
killTimer(PLAYER_ONLINE_TIMER_ID);
|
|
ui.NavigateToScene(m_iPad, eUIScene_DLCOffersMenu, param);
|
|
break;
|
|
}
|
|
case eControl_MSSignIn:
|
|
{
|
|
// Open the Microsoft Account sign-in dialog
|
|
ui.NavigateToScene(m_iPad, eUIScene_MSAuth, nullptr, eUILayer_Popup, eUIGroup_Fullscreen);
|
|
break;
|
|
}
|
|
};
|
|
}
|
|
|
|
void UIScene_DLCMainMenu::handleTimerComplete(int id)
|
|
{
|
|
#if ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__)
|
|
switch(id)
|
|
{
|
|
case PLAYER_ONLINE_TIMER_ID:
|
|
#ifndef _WINDOWS64
|
|
if(ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())==false)
|
|
{
|
|
// check the player hasn't gone offline
|
|
// If they have, bring up the PSN warning and exit from the leaderboards
|
|
unsigned int uiIDA[1];
|
|
uiIDA[0]=IDS_OK;
|
|
C4JStorage::EMessageResult result = ui.RequestErrorMessage( IDS_CONNECTION_LOST, g_NetworkManager.CorrectErrorIDS(IDS_CONNECTION_LOST_LIVE_NO_EXIT), uiIDA,1,ProfileManager.GetPrimaryPad(),UIScene_DLCMainMenu::ExitDLCMainMenu,this);
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int UIScene_DLCMainMenu::ExitDLCMainMenu(void *pParam,int iPad,C4JStorage::EMessageResult result)
|
|
{
|
|
UIScene_DLCMainMenu* pClass = static_cast<UIScene_DLCMainMenu *>(pParam);
|
|
|
|
#if defined __ORBIS__ || defined __PSVITA__
|
|
app.GetCommerce()->HidePsStoreIcon();
|
|
#endif
|
|
pClass->navigateBack();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void UIScene_DLCMainMenu::handleGainFocus(bool navBack)
|
|
{
|
|
UIScene::handleGainFocus(navBack);
|
|
|
|
updateTooltips();
|
|
|
|
// Allow tick() to re-check auth state after navigating back.
|
|
m_authLabelUpdated = false;
|
|
|
|
if(navBack)
|
|
{
|
|
// Refresh the sign-in button label after returning from MSAuth.
|
|
if(MCAuthManager::Get().IsJavaLoggedIn())
|
|
{
|
|
MCAuth::JavaSession s = MCAuthManager::Get().GetJavaSession();
|
|
std::wstring name(s.username.begin(), s.username.end());
|
|
DLCMenuLog("[DLCMainMenu] handleGainFocus: logged in as '%s'\n",
|
|
s.username.c_str());
|
|
m_labelXboxStore.setLabel(name);
|
|
}
|
|
else
|
|
{
|
|
m_labelXboxStore.setLabel(L"Sign in with Microsoft");
|
|
}
|
|
|
|
// add the timer back in
|
|
#if ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ )
|
|
addTimer( PLAYER_ONLINE_TIMER_ID, PLAYER_ONLINE_TIMER_TIME );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void UIScene_DLCMainMenu::tick()
|
|
{
|
|
UIScene::tick();
|
|
|
|
// Update sign-in label when background session restore completes.
|
|
if(!m_authLabelUpdated)
|
|
{
|
|
auto state = MCAuthManager::Get().GetState();
|
|
bool loggedIn = MCAuthManager::Get().IsJavaLoggedIn();
|
|
|
|
if(loggedIn)
|
|
{
|
|
MCAuth::JavaSession s = MCAuthManager::Get().GetJavaSession();
|
|
std::wstring name(s.username.begin(), s.username.end());
|
|
DLCMenuLog("[DLCMainMenu] tick: Auth restored! username='%s', setting label\n",
|
|
s.username.c_str());
|
|
m_labelXboxStore.setLabel(name);
|
|
m_authLabelUpdated = true;
|
|
}
|
|
else if(state == MCAuthManager::State::Idle ||
|
|
state == MCAuthManager::State::Failed)
|
|
{
|
|
DLCMenuLog("[DLCMainMenu] tick: Restore finished without login (state=%d), stop polling\n",
|
|
(int)state);
|
|
// Restore attempt finished but failed — stop checking.
|
|
m_authLabelUpdated = true;
|
|
}
|
|
// else: still authenticating in background, keep polling
|
|
}
|
|
|
|
#if defined(__PS3__) || defined(__ORBIS__) || defined (__PSVITA__)
|
|
if((m_bCategoriesShown==false) && (app.GetCommerceCategoriesRetrieved()))
|
|
{
|
|
// disable the timer display on this menu
|
|
m_Timer.setVisible(false);
|
|
m_bCategoriesShown=true;
|
|
|
|
// add the categories to the list box
|
|
SonyCommerce::CategoryInfo *pCategories=app.GetCategoryInfo();
|
|
std::list<SonyCommerce::CategoryInfoSub>::iterator iter = pCategories->subCategories.begin();
|
|
SonyCommerce::CategoryInfoSub category;
|
|
for(int i=0;i<pCategories->countOfSubCategories;i++)
|
|
{
|
|
// add a button in with the subcategory
|
|
category = (SonyCommerce::CategoryInfoSub)(*iter);
|
|
|
|
string teststring=category.categoryName;
|
|
m_buttonListOffers.addItem(teststring,i);
|
|
|
|
iter++;
|
|
}
|
|
|
|
// set the focus to the first thing in the categories if there are any
|
|
if(pCategories->countOfSubCategories>0)
|
|
{
|
|
m_buttonListOffers.setFocus(true);
|
|
}
|
|
else
|
|
{
|
|
#if defined __ORBIS__ || defined __PSVITA__ || defined __PS3__
|
|
app.CheckForEmptyStore(ProfileManager.GetPrimaryPad());
|
|
#endif
|
|
// need to display text to say no downloadable content available yet
|
|
m_labelOffers.setLabel(app.GetString(IDS_NO_DLCCATEGORIES));
|
|
|
|
#ifdef __ORBIS__
|
|
// 4J-JEV: TRC Requirement (R4055), need to display this system message.
|
|
ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_EMPTY_STORE, ProfileManager.GetPrimaryPad() );
|
|
#endif
|
|
}
|
|
|
|
}
|
|
#endif
|
|
}
|
|
|