diff --git a/targets/app/common/DLCController.cpp b/targets/app/common/DLCController.cpp new file mode 100644 index 000000000..c29963d71 --- /dev/null +++ b/targets/app/common/DLCController.cpp @@ -0,0 +1,719 @@ +#include "app/common/DLCController.h" + +#include "app/common/Game.h" +#include "app/common/DLC/DLCPack.h" +#include "app/common/DLC/DLCManager.h" +#include "app/common/DLC/DLCSkinFile.h" +#include "app/linux/LinuxGame.h" +#include "app/linux/Linux_UIController.h" +#include "minecraft/client/Minecraft.h" +#include "minecraft/client/skins/TexturePack.h" +#include "minecraft/client/skins/TexturePackRepository.h" +#include "platform/sdl2/Storage.h" +#include "platform/sdl2/Profile.h" +#include "platform/XboxStubs.h" + +#include +#include + +DLCController::DLCController() { + m_pDLCFileBuffer = nullptr; + m_dwDLCFileSize = 0; + m_bDefaultCapeInstallAttempted = false; + m_bDLCInstallProcessCompleted = false; + m_bDLCInstallPending = false; + m_iTotalDLC = 0; + m_iTotalDLCInstalled = 0; + m_bNewDLCAvailable = false; + m_bSeenNewDLCTip = false; + m_iDLCOfferC = 0; + m_bAllDLCContentRetrieved = true; + m_bAllTMSContentRetrieved = true; + m_bTickTMSDLCFiles = true; +} + +std::unordered_map DLCController::MojangData; +std::unordered_map DLCController::DLCTextures_PackID; +std::unordered_map DLCController::DLCInfo_Trial; +std::unordered_map DLCController::DLCInfo_Full; +std::unordered_map DLCController::DLCInfo_SkinName; + +std::uint32_t DLCController::m_dwContentTypeA[e_Marketplace_MAX] = { + XMARKETPLACE_OFFERING_TYPE_CONTENT, + XMARKETPLACE_OFFERING_TYPE_THEME, + XMARKETPLACE_OFFERING_TYPE_AVATARITEM, + XMARKETPLACE_OFFERING_TYPE_TILE, +}; + +int DLCController::marketplaceCountsCallback( + void* pParam, C4JStorage::DLC_TMS_DETAILS* pTMSDetails, int iPad) { + app.DebugPrintf("Marketplace Counts= New - %d Total - %d\n", + pTMSDetails->dwNewOffers, pTMSDetails->dwTotalOffers); + + if (pTMSDetails->dwNewOffers > 0) { + app.m_dlcController.m_bNewDLCAvailable = true; + app.m_dlcController.m_bSeenNewDLCTip = false; + } else { + app.m_dlcController.m_bNewDLCAvailable = false; + app.m_dlcController.m_bSeenNewDLCTip = true; + } + + return 0; +} + +bool DLCController::startInstallDLCProcess(int iPad) { + app.DebugPrintf("--- DLCController::startInstallDLCProcess: pad=%i.\n", + iPad); + + if ((dlcInstallProcessCompleted() == false) && + (m_bDLCInstallPending == false)) { + app.m_dlcManager.resetUnnamedCorruptCount(); + m_bDLCInstallPending = true; + m_iTotalDLC = 0; + m_iTotalDLCInstalled = 0; + app.DebugPrintf( + "--- DLCController::startInstallDLCProcess - " + "StorageManager.GetInstalledDLC\n"); + + StorageManager.GetInstalledDLC( + iPad, [this](int iInstalledC, int pad) { + return dlcInstalledCallback(iInstalledC, pad); + }); + return true; + } else { + app.DebugPrintf( + "--- DLCController::startInstallDLCProcess - nothing to do\n"); + return false; + } +} + +int DLCController::dlcInstalledCallback(int iInstalledC, int iPad) { + app.DebugPrintf( + "--- DLCController::dlcInstalledCallback: totalDLC=%i, pad=%i.\n", + iInstalledC, iPad); + m_iTotalDLC = iInstalledC; + mountNextDLC(iPad); + return 0; +} + +void DLCController::mountNextDLC(int iPad) { + app.DebugPrintf("--- DLCController::mountNextDLC: pad=%i.\n", iPad); + if (m_iTotalDLCInstalled < m_iTotalDLC) { + if (StorageManager.MountInstalledDLC( + iPad, m_iTotalDLCInstalled, + [this](int pad, std::uint32_t dwErr, + std::uint32_t dwLicenceMask) { + return dlcMountedCallback(pad, dwErr, dwLicenceMask); + }) != ERROR_IO_PENDING) { + app.DebugPrintf("Failed to mount DLC %d for pad %d\n", + m_iTotalDLCInstalled, iPad); + ++m_iTotalDLCInstalled; + mountNextDLC(iPad); + } else { + app.DebugPrintf("StorageManager.MountInstalledDLC ok\n"); + } + } else { + m_bDLCInstallPending = false; + m_bDLCInstallProcessCompleted = true; + ui.HandleDLCMountingComplete(); + } +} + +#if defined(_WINDOWS64) +#define CONTENT_DATA_DISPLAY_NAME(a) (a.szDisplayName) +#else +#define CONTENT_DATA_DISPLAY_NAME(a) (a.wszDisplayName) +#endif + +int DLCController::dlcMountedCallback(int iPad, std::uint32_t dwErr, + std::uint32_t dwLicenceMask) { +#if defined(_WINDOWS64) + app.DebugPrintf("--- DLCController::dlcMountedCallback\n"); + + if (dwErr != ERROR_SUCCESS) { + app.DebugPrintf("Failed to mount DLC for pad %d: %u\n", iPad, dwErr); + app.m_dlcManager.incrementUnnamedCorruptCount(); + } else { + XCONTENT_DATA ContentData = + StorageManager.GetDLC(m_iTotalDLCInstalled); + + DLCPack* pack = + app.m_dlcManager.getPack(CONTENT_DATA_DISPLAY_NAME(ContentData)); + + if (pack != nullptr && pack->IsCorrupt()) { + app.DebugPrintf( + "Pack '%ls' is corrupt, removing it from the DLC Manager.\n", + CONTENT_DATA_DISPLAY_NAME(ContentData)); + app.m_dlcManager.removePack(pack); + pack = nullptr; + } + + if (pack == nullptr) { + app.DebugPrintf("Pack \"%ls\" is not installed, so adding it\n", + CONTENT_DATA_DISPLAY_NAME(ContentData)); + +#if defined(_WINDOWS64) + pack = new DLCPack(ContentData.szDisplayName, dwLicenceMask); +#else + pack = new DLCPack(ContentData.wszDisplayName, dwLicenceMask); +#endif + pack->SetDLCMountIndex(m_iTotalDLCInstalled); + pack->SetDLCDeviceID(ContentData.DeviceID); + app.m_dlcManager.addPack(pack); + handleDLC(pack); + + if (pack->getDLCItemsCount(DLCManager::e_DLCType_Texture) > 0) { + Minecraft::GetInstance()->skins->addTexturePackFromDLC( + pack, pack->GetPackId()); + } + } else { + app.DebugPrintf( + "Pack \"%ls\" is already installed. Updating license to %u\n", + CONTENT_DATA_DISPLAY_NAME(ContentData), dwLicenceMask); + + pack->SetDLCMountIndex(m_iTotalDLCInstalled); + pack->SetDLCDeviceID(ContentData.DeviceID); + pack->updateLicenseMask(dwLicenceMask); + } + + StorageManager.UnmountInstalledDLC(); + } + ++m_iTotalDLCInstalled; + mountNextDLC(iPad); +#endif + return 0; +} +#undef CONTENT_DATA_DISPLAY_NAME + +void DLCController::handleDLC(DLCPack* pack) { + unsigned int dwFilesProcessed = 0; +#if defined(_WINDOWS64) || defined(__linux__) + std::vector dlcFilenames; +#endif + StorageManager.GetMountedDLCFileList("DLCDrive", dlcFilenames); + for (int i = 0; i < dlcFilenames.size(); i++) { + app.m_dlcManager.readDLCDataFile(dwFilesProcessed, dlcFilenames[i], + pack); + } + if (dwFilesProcessed == 0) app.m_dlcManager.removePack(pack); +} + +void DLCController::addCreditText(const wchar_t* lpStr) { + app.DebugPrintf("ADDING CREDIT - %ls\n", lpStr); + SCreditTextItemDef* pCreditStruct = new SCreditTextItemDef; + pCreditStruct->m_eType = eSmallText; + pCreditStruct->m_iStringID[0] = NO_TRANSLATED_STRING; + pCreditStruct->m_iStringID[1] = NO_TRANSLATED_STRING; + pCreditStruct->m_Text = new wchar_t[wcslen(lpStr) + 1]; + wcscpy((wchar_t*)pCreditStruct->m_Text, lpStr); + vDLCCredits.push_back(pCreditStruct); +} + +bool DLCController::alreadySeenCreditText(const std::wstring& wstemp) { + for (unsigned int i = 0; i < m_vCreditText.size(); i++) { + std::wstring temp = m_vCreditText.at(i); + if (temp.compare(wstemp) == 0) { + return true; + } + } + m_vCreditText.push_back((wchar_t*)wstemp.c_str()); + return false; +} + +unsigned int DLCController::getDLCCreditsCount() { + return (unsigned int)vDLCCredits.size(); +} + +SCreditTextItemDef* DLCController::getDLCCredits(int iIndex) { + return vDLCCredits.at(iIndex); +} + +#if defined(_WINDOWS64) +int32_t DLCController::registerDLCData(wchar_t* pType, wchar_t* pBannerName, + int iGender, uint64_t ullOfferID_Full, + uint64_t ullOfferID_Trial, + wchar_t* pFirstSkin, + unsigned int uiSortIndex, int iConfig, + wchar_t* pDataFile) { + int32_t hr = 0; + DLC_INFO* pDLCData = new DLC_INFO; + memset(pDLCData, 0, sizeof(DLC_INFO)); + pDLCData->ullOfferID_Full = ullOfferID_Full; + pDLCData->ullOfferID_Trial = ullOfferID_Trial; + pDLCData->eDLCType = e_DLC_NotDefined; + pDLCData->iGender = iGender; + pDLCData->uiSortIndex = uiSortIndex; + pDLCData->iConfig = iConfig; + + if (pBannerName != L"") { + wcsncpy_s(pDLCData->wchBanner, pBannerName, MAX_BANNERNAME_SIZE); + } + if (pDataFile[0] != 0) { + wcsncpy_s(pDLCData->wchDataFile, pDataFile, MAX_BANNERNAME_SIZE); + } + + if (pType != nullptr) { + if (wcscmp(pType, L"Skin") == 0) { + pDLCData->eDLCType = e_DLC_SkinPack; + } else if (wcscmp(pType, L"Gamerpic") == 0) { + pDLCData->eDLCType = e_DLC_Gamerpics; + } else if (wcscmp(pType, L"Theme") == 0) { + pDLCData->eDLCType = e_DLC_Themes; + } else if (wcscmp(pType, L"Avatar") == 0) { + pDLCData->eDLCType = e_DLC_AvatarItems; + } else if (wcscmp(pType, L"MashUpPack") == 0) { + pDLCData->eDLCType = e_DLC_MashupPacks; + DLCTextures_PackID[pDLCData->iConfig] = ullOfferID_Full; + } else if (wcscmp(pType, L"TexturePack") == 0) { + pDLCData->eDLCType = e_DLC_TexturePacks; + DLCTextures_PackID[pDLCData->iConfig] = ullOfferID_Full; + } + } + + if (ullOfferID_Trial != 0ll) DLCInfo_Trial[ullOfferID_Trial] = pDLCData; + if (ullOfferID_Full != 0ll) DLCInfo_Full[ullOfferID_Full] = pDLCData; + if (pFirstSkin[0] != 0) DLCInfo_SkinName[pFirstSkin] = ullOfferID_Full; + + return hr; +} +#elif defined(__linux__) +int32_t DLCController::registerDLCData(wchar_t* pType, wchar_t* pBannerName, + int iGender, uint64_t ullOfferID_Full, + uint64_t ullOfferID_Trial, + wchar_t* pFirstSkin, + unsigned int uiSortIndex, int iConfig, + wchar_t* pDataFile) { + fprintf(stderr, + "warning: DLCController::registerDLCData unimplemented for " + "platform `__linux__`\n"); + return 0; +} +#endif + +bool DLCController::getDLCFullOfferIDForSkinID(const std::wstring& FirstSkin, + uint64_t* pullVal) { + auto it = DLCInfo_SkinName.find(FirstSkin); + if (it == DLCInfo_SkinName.end()) { + return false; + } else { + *pullVal = (uint64_t)it->second; + return true; + } +} + +bool DLCController::getDLCFullOfferIDForPackID(const int iPackID, + uint64_t* pullVal) { + auto it = DLCTextures_PackID.find(iPackID); + if (it == DLCTextures_PackID.end()) { + *pullVal = (uint64_t)0; + return false; + } else { + *pullVal = (uint64_t)it->second; + return true; + } +} + +DLC_INFO* DLCController::getDLCInfoForTrialOfferID( + uint64_t ullOfferID_Trial) { + if (DLCInfo_Trial.size() > 0) { + auto it = DLCInfo_Trial.find(ullOfferID_Trial); + if (it == DLCInfo_Trial.end()) { + return nullptr; + } else { + return it->second; + } + } else + return nullptr; +} + +DLC_INFO* DLCController::getDLCInfoForFullOfferID(uint64_t ullOfferID_Full) { + if (DLCInfo_Full.size() > 0) { + auto it = DLCInfo_Full.find(ullOfferID_Full); + if (it == DLCInfo_Full.end()) { + return nullptr; + } else { + return it->second; + } + } else + return nullptr; +} + +DLC_INFO* DLCController::getDLCInfoTrialOffer(int iIndex) { + std::unordered_map::iterator it = + DLCInfo_Trial.begin(); + for (int i = 0; i < iIndex; i++) { + ++it; + } + return it->second; +} + +DLC_INFO* DLCController::getDLCInfoFullOffer(int iIndex) { + std::unordered_map::iterator it = DLCInfo_Full.begin(); + for (int i = 0; i < iIndex; i++) { + ++it; + } + return it->second; +} + +uint64_t DLCController::getDLCInfoTexturesFullOffer(int iIndex) { + std::unordered_map::iterator it = DLCTextures_PackID.begin(); + for (int i = 0; i < iIndex; i++) { + ++it; + } + return it->second; +} + +int DLCController::getDLCInfoTrialOffersCount() { + return (int)DLCInfo_Trial.size(); +} + +int DLCController::getDLCInfoFullOffersCount() { + return (int)DLCInfo_Full.size(); +} + +int DLCController::getDLCInfoTexturesOffersCount() { + return (int)DLCTextures_PackID.size(); +} + +unsigned int DLCController::addDLCRequest(eDLCMarketplaceType eType, + bool bPromote) { + { + std::lock_guard lock(csDLCDownloadQueue); + + int iPosition = 0; + for (auto it = m_DLCDownloadQueue.begin(); + it != m_DLCDownloadQueue.end(); ++it) { + DLCRequest* pCurrent = *it; + if (pCurrent->dwType == m_dwContentTypeA[eType]) { + if (pCurrent->eState == e_DLC_ContentState_Retrieving || + pCurrent->eState == e_DLC_ContentState_Retrieved) { + return 0; + } else { + if (bPromote) { + m_DLCDownloadQueue.erase(m_DLCDownloadQueue.begin() + + iPosition); + m_DLCDownloadQueue.insert(m_DLCDownloadQueue.begin(), + pCurrent); + } + return 0; + } + } + iPosition++; + } + + DLCRequest* pDLCreq = new DLCRequest; + pDLCreq->dwType = m_dwContentTypeA[eType]; + pDLCreq->eState = e_DLC_ContentState_Idle; + m_DLCDownloadQueue.push_back(pDLCreq); + m_bAllDLCContentRetrieved = false; + } + + app.DebugPrintf("[Consoles_App] Added DLC request.\n"); + return 1; +} + +bool DLCController::retrieveNextDLCContent() { + int primPad = ProfileManager.GetPrimaryPad(); + if (primPad == -1 || !ProfileManager.IsSignedInLive(primPad)) { + return true; + } + + { + std::lock_guard lock(csDLCDownloadQueue); + for (auto it = m_DLCDownloadQueue.begin(); + it != m_DLCDownloadQueue.end(); ++it) { + DLCRequest* pCurrent = *it; + if (pCurrent->eState == e_DLC_ContentState_Retrieving) { + return true; + } + } + + for (auto it = m_DLCDownloadQueue.begin(); + it != m_DLCDownloadQueue.end(); ++it) { + DLCRequest* pCurrent = *it; + if (pCurrent->eState == e_DLC_ContentState_Idle) { +#if defined(_DEBUG) + app.DebugPrintf("RetrieveNextDLCContent - type = %d\n", + pCurrent->dwType); +#endif + C4JStorage::EDLCStatus status = StorageManager.GetDLCOffers( + ProfileManager.GetPrimaryPad(), + [this](int iOfferC, std::uint32_t dwType, int pad) { + return dlcOffersReturned(iOfferC, dwType, pad); + }, + pCurrent->dwType); + if (status == C4JStorage::EDLC_Pending) { + pCurrent->eState = e_DLC_ContentState_Retrieving; + } else { + app.DebugPrintf("RetrieveNextDLCContent - PROBLEM\n"); + pCurrent->eState = e_DLC_ContentState_Retrieved; + } + return true; + } + } + } + + app.DebugPrintf("[Consoles_App] Finished downloading dlc content.\n"); + return false; +} + +bool DLCController::checkTMSDLCCanStop() { + std::lock_guard lock(csTMSPPDownloadQueue); + for (auto it = m_TMSPPDownloadQueue.begin(); + it != m_TMSPPDownloadQueue.end(); ++it) { + TMSPPRequest* pCurrent = *it; + if (pCurrent->eState == e_TMS_ContentState_Retrieving) { + return false; + } + } + return true; +} + +int DLCController::dlcOffersReturned(int iOfferC, std::uint32_t dwType, + int iPad) { + { + std::lock_guard lock(csTMSPPDownloadQueue); + for (auto it = m_DLCDownloadQueue.begin(); + it != m_DLCDownloadQueue.end(); ++it) { + DLCRequest* pCurrent = *it; + if (pCurrent->dwType == static_cast(dwType)) { + m_iDLCOfferC = iOfferC; + app.DebugPrintf( + "DLCOffersReturned - type %u, count %d - setting to " + "retrieved\n", + dwType, iOfferC); + pCurrent->eState = e_DLC_ContentState_Retrieved; + break; + } + } + } + return 0; +} + +eDLCContentType DLCController::find_eDLCContentType(std::uint32_t dwType) { + for (int i = 0; i < e_DLC_MAX; i++) { + if (m_dwContentTypeA[i] == dwType) { + return (eDLCContentType)i; + } + } + return (eDLCContentType)0; +} + +bool DLCController::dlcContentRetrieved(eDLCMarketplaceType eType) { + std::lock_guard lock(csDLCDownloadQueue); + for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); + ++it) { + DLCRequest* pCurrent = *it; + if ((pCurrent->dwType == m_dwContentTypeA[eType]) && + (pCurrent->eState == e_DLC_ContentState_Retrieved)) { + return true; + } + } + return false; +} + +void DLCController::tickDLCOffersRetrieved() { + if (!m_bAllDLCContentRetrieved) { + if (!retrieveNextDLCContent()) { + app.DebugPrintf("[Consoles_App] All content retrieved.\n"); + m_bAllDLCContentRetrieved = true; + } + } +} + +void DLCController::clearAndResetDLCDownloadQueue() { + app.DebugPrintf("[Consoles_App] Clear and reset download queue.\n"); + + int iPosition = 0; + { + std::lock_guard lock(csTMSPPDownloadQueue); + for (auto it = m_DLCDownloadQueue.begin(); + it != m_DLCDownloadQueue.end(); ++it) { + DLCRequest* pCurrent = *it; + delete pCurrent; + iPosition++; + } + m_DLCDownloadQueue.clear(); + m_bAllDLCContentRetrieved = true; + } +} + +bool DLCController::retrieveNextTMSPPContent() { return false; } + +void DLCController::tickTMSPPFilesRetrieved() { + if (m_bTickTMSDLCFiles && !m_bAllTMSContentRetrieved) { + if (retrieveNextTMSPPContent() == false) { + m_bAllTMSContentRetrieved = true; + } + } +} + +void DLCController::clearTMSPPFilesRetrieved() { + int iPosition = 0; + { + std::lock_guard lock(csTMSPPDownloadQueue); + for (auto it = m_TMSPPDownloadQueue.begin(); + it != m_TMSPPDownloadQueue.end(); ++it) { + TMSPPRequest* pCurrent = *it; + delete pCurrent; + iPosition++; + } + m_TMSPPDownloadQueue.clear(); + m_bAllTMSContentRetrieved = true; + } +} + +unsigned int DLCController::addTMSPPFileTypeRequest(eDLCContentType eType, + bool bPromote) { + std::lock_guard lock(csTMSPPDownloadQueue); + + if (eType == e_DLC_TexturePackData) { + int iCount = getDLCInfoFullOffersCount(); + + for (int i = 0; i < iCount; i++) { + DLC_INFO* pDLC = getDLCInfoFullOffer(i); + + if ((pDLC->eDLCType == e_DLC_TexturePacks) || + (pDLC->eDLCType == e_DLC_MashupPacks)) { + if (pDLC->wchDataFile[0] != 0) { + { + bool bPresent = app.IsFileInTPD(pDLC->iConfig); + + if (!bPresent) { + bool bAlreadyInQueue = false; + for (auto it = m_TMSPPDownloadQueue.begin(); + it != m_TMSPPDownloadQueue.end(); ++it) { + TMSPPRequest* pCurrent = *it; + if (wcscmp(pDLC->wchDataFile, + pCurrent->wchFilename) == 0) { + bAlreadyInQueue = true; + break; + } + } + + if (!bAlreadyInQueue) { + TMSPPRequest* pTMSPPreq = new TMSPPRequest; + pTMSPPreq->CallbackFunc = + &DLCController::tmsPPFileReturned; + pTMSPPreq->lpCallbackParam = this; + pTMSPPreq->eStorageFacility = + C4JStorage::eGlobalStorage_Title; + pTMSPPreq->eFileTypeVal = + C4JStorage::TMS_FILETYPE_BINARY; + memcpy(pTMSPPreq->wchFilename, + pDLC->wchDataFile, + sizeof(wchar_t) * MAX_BANNERNAME_SIZE); + pTMSPPreq->eType = e_DLC_TexturePackData; + pTMSPPreq->eState = e_TMS_ContentState_Queued; + m_bAllTMSContentRetrieved = false; + m_TMSPPDownloadQueue.push_back(pTMSPPreq); + } + } else { + app.DebugPrintf( + "Texture data already present in the TPD\n"); + } + } + } + } + } + } else { + int iCount; + iCount = getDLCInfoFullOffersCount(); + for (int i = 0; i < iCount; i++) { + DLC_INFO* pDLC = getDLCInfoFullOffer(i); + if (pDLC->eDLCType == eType) { + wchar_t* cString = pDLC->wchBanner; + { + bool bPresent = app.IsFileInMemoryTextures(cString); + + if (!bPresent) { + bool bAlreadyInQueue = false; + for (auto it = m_TMSPPDownloadQueue.begin(); + it != m_TMSPPDownloadQueue.end(); ++it) { + TMSPPRequest* pCurrent = *it; + if (wcscmp(pDLC->wchBanner, + pCurrent->wchFilename) == 0) { + bAlreadyInQueue = true; + break; + } + } + + if (!bAlreadyInQueue) { + TMSPPRequest* pTMSPPreq = new TMSPPRequest; + memset(pTMSPPreq, 0, sizeof(TMSPPRequest)); + pTMSPPreq->CallbackFunc = + &DLCController::tmsPPFileReturned; + pTMSPPreq->lpCallbackParam = this; + pTMSPPreq->eStorageFacility = + C4JStorage::eGlobalStorage_Title; + pTMSPPreq->eFileTypeVal = + C4JStorage::TMS_FILETYPE_BINARY; + memcpy(pTMSPPreq->wchFilename, pDLC->wchBanner, + sizeof(wchar_t) * MAX_BANNERNAME_SIZE); + pTMSPPreq->eType = eType; + pTMSPPreq->eState = e_TMS_ContentState_Queued; + m_bAllTMSContentRetrieved = false; + m_TMSPPDownloadQueue.push_back(pTMSPPreq); + app.DebugPrintf( + "===m_TMSPPDownloadQueue Adding %ls, q size is " + "%d\n", + pTMSPPreq->wchFilename, + m_TMSPPDownloadQueue.size()); + } + } + } + } + } + } + + return 1; +} + +int DLCController::tmsPPFileReturned(void* pParam, int iPad, int iUserData, + C4JStorage::PTMSPP_FILEDATA pFileData, + const char* szFilename) { + DLCController* pClass = (DLCController*)pParam; + + { + std::lock_guard lock(pClass->csTMSPPDownloadQueue); + for (auto it = pClass->m_TMSPPDownloadQueue.begin(); + it != pClass->m_TMSPPDownloadQueue.end(); ++it) { + TMSPPRequest* pCurrent = *it; +#if defined(_WINDOWS64) + char szFile[MAX_TMSFILENAME_SIZE]; + wcstombs(szFile, pCurrent->wchFilename, MAX_TMSFILENAME_SIZE); + + if (strcmp(szFilename, szFile) == 0) +#endif + { + pCurrent->eState = e_TMS_ContentState_Retrieved; + + if (pFileData != nullptr) { + switch (pCurrent->eType) { + case e_DLC_TexturePackData: { + app.DebugPrintf("--- Got texturepack data %ls\n", + pCurrent->wchFilename); + int iConfig = + app.GetTPConfigVal(pCurrent->wchFilename); + app.AddMemoryTPDFile(iConfig, pFileData->pbData, + pFileData->size); + } break; + default: + app.DebugPrintf("--- Got image data - %ls\n", + pCurrent->wchFilename); + app.AddMemoryTextureFile(pCurrent->wchFilename, + pFileData->pbData, + pFileData->size); + break; + } + } else { + app.DebugPrintf("TMSImageReturned failed (%s)...\n", + szFilename); + } + break; + } + } + } + + return 0; +} diff --git a/targets/app/common/DLCController.h b/targets/app/common/DLCController.h new file mode 100644 index 000000000..0fc5d7425 --- /dev/null +++ b/targets/app/common/DLCController.h @@ -0,0 +1,137 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "app/common/App_structs.h" +#include "app/common/DLC/DLCManager.h" +#include "platform/sdl2/Storage.h" +#include "platform/XboxStubs.h" + +struct SCreditTextItemDef; + +class DLCPack; + +class DLCController { +public: + DLCController(); + + // Install process + bool startInstallDLCProcess(int iPad); + int dlcInstalledCallback(int iInstalledC, int iPad); + void mountNextDLC(int iPad); + int dlcMountedCallback(int iPad, std::uint32_t dwErr, + std::uint32_t dwLicenceMask); + void handleDLC(DLCPack* pack); + + bool dlcInstallPending() { return m_bDLCInstallPending; } + bool dlcInstallProcessCompleted() { return m_bDLCInstallProcessCompleted; } + void clearDLCInstalled() { m_bDLCInstallProcessCompleted = false; } + + static int marketplaceCountsCallback(void* pParam, + C4JStorage::DLC_TMS_DETAILS*, + int iPad); + + // DLC info registration + static int32_t registerDLCData(wchar_t*, wchar_t*, int, uint64_t, uint64_t, + wchar_t*, unsigned int, int, + wchar_t* pDataFile); + bool getDLCFullOfferIDForSkinID(const std::wstring& FirstSkin, + uint64_t* pullVal); + bool getDLCFullOfferIDForPackID(const int iPackID, uint64_t* pullVal); + DLC_INFO* getDLCInfoForTrialOfferID(uint64_t ullOfferID_Trial); + DLC_INFO* getDLCInfoForFullOfferID(uint64_t ullOfferID_Full); + DLC_INFO* getDLCInfoTrialOffer(int iIndex); + DLC_INFO* getDLCInfoFullOffer(int iIndex); + uint64_t getDLCInfoTexturesFullOffer(int iIndex); + int getDLCInfoTrialOffersCount(); + int getDLCInfoFullOffersCount(); + int getDLCInfoTexturesOffersCount(); + + // DLC content/offers + unsigned int addDLCRequest(eDLCMarketplaceType eContentType, + bool bPromote = false); + bool retrieveNextDLCContent(); + bool checkTMSDLCCanStop(); + int dlcOffersReturned(int iOfferC, std::uint32_t dwType, int iPad); + std::uint32_t getDLCContentType(eDLCContentType eType) { + return m_dwContentTypeA[eType]; + } + eDLCContentType find_eDLCContentType(std::uint32_t dwType); + int getDLCOffersCount() { return m_iDLCOfferC; } + bool dlcContentRetrieved(eDLCMarketplaceType eType); + void tickDLCOffersRetrieved(); + void clearAndResetDLCDownloadQueue(); + + // TMS/TMSPP + bool retrieveNextTMSPPContent(); + void tickTMSPPFilesRetrieved(); + void clearTMSPPFilesRetrieved(); + unsigned int addTMSPPFileTypeRequest(eDLCContentType eType, + bool bPromote = false); + static int tmsPPFileReturned(void* pParam, int iPad, int iUserData, + C4JStorage::PTMSPP_FILEDATA pFileData, + const char* szFilename); + + // Credit text + void addCreditText(const wchar_t* lpStr); + bool alreadySeenCreditText(const std::wstring& wstemp); + unsigned int getDLCCreditsCount(); + SCreditTextItemDef* getDLCCredits(int iIndex); + + // New DLC available + void clearNewDLCAvailable() { + m_bNewDLCAvailable = false; + m_bSeenNewDLCTip = true; + } + bool getNewDLCAvailable() { return m_bNewDLCAvailable; } + void displayNewDLCTipAgain() { m_bSeenNewDLCTip = false; } + bool displayNewDLCTip() { + if (!m_bSeenNewDLCTip) { + m_bSeenNewDLCTip = true; + return true; + } else + return false; + } + + void setTickTMSDLCFiles(bool bVal) { m_bTickTMSDLCFiles = bVal; } + + // Public data needed by other parts + std::vector m_vCreditText; + std::uint8_t* m_pDLCFileBuffer; + unsigned int m_dwDLCFileSize; + + // DLC install counters (accessed by dlcMountedCallback) + int m_iTotalDLC; + int m_iTotalDLCInstalled; + + // Static maps + static std::unordered_map MojangData; + static std::unordered_map DLCTextures_PackID; + static std::unordered_map DLCInfo_Trial; + static std::unordered_map DLCInfo_Full; + static std::unordered_map DLCInfo_SkinName; + static std::uint32_t m_dwContentTypeA[e_Marketplace_MAX]; + +private: + std::vector vDLCCredits; + std::vector m_DLCDownloadQueue; + std::vector m_TMSPPDownloadQueue; + + int m_iDLCOfferC; + bool m_bAllDLCContentRetrieved; + bool m_bAllTMSContentRetrieved; + bool m_bTickTMSDLCFiles; + std::mutex csDLCDownloadQueue; + std::mutex csTMSPPDownloadQueue; + + bool m_bDLCInstallProcessCompleted; + bool m_bDLCInstallPending; + bool m_bDefaultCapeInstallAttempted; + + bool m_bNewDLCAvailable; + bool m_bSeenNewDLCTip; +}; diff --git a/targets/app/common/Game.cpp b/targets/app/common/Game.cpp index 17b0c36a0..55a292a7e 100644 --- a/targets/app/common/Game.cpp +++ b/targets/app/common/Game.cpp @@ -109,7 +109,6 @@ class ModelPart; class SignTileEntity; // Game app; -unsigned int Game::m_uiLastSignInData = 0; const float Game::fSafeZoneX = 64.0f; // 5% of 1280 const float Game::fSafeZoneY = 36.0f; // 5% of 720 @@ -118,8 +117,6 @@ Game::Game() { GameHostOptions::init(&m_uiGameHostSettings); if (GAME_SETTINGS_PROFILE_DATA_BYTES != sizeof(GAME_SETTINGS)) { - // 4J Stu - See comment for GAME_SETTINGS_PROFILE_DATA_BYTES in - // Xbox_App.h DebugPrintf( "WARNING: The size of the profile GAME_SETTINGS struct has " "changed, so all stat data is likely incorrect. Is: %d, Should be: " @@ -131,75 +128,26 @@ Game::Game() { } for (int i = 0; i < XUSER_MAX_COUNT; i++) { - m_eTMSAction[i] = eTMSAction_Idle; - m_eXuiAction[i] = eAppAction_Idle; - m_eXuiActionParam[i] = nullptr; - // m_dwAdditionalModelParts[i] = 0; - - if (FAILED(XUserGetSigninInfo(i, - XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY, - &m_currentSigninInfo[i]))) { - m_currentSigninInfo[i].xuid = INVALID_XUID; - m_currentSigninInfo[i].dwGuestNumber = 0; - } DebugPrintf("Player at index %d has guest number %d\n", i, - m_currentSigninInfo[i].dwGuestNumber); - - m_uiOpacityCountDown[i] = 0; + m_networkController.m_currentSigninInfo[i].dwGuestNumber); } - m_eGlobalXuiAction = eAppAction_Idle; - m_eGlobalXuiServerAction = eXuiServerAction_Idle; m_bResourcesLoaded = false; m_bGameStarted = false; m_bIsAppPaused = false; - // m_bSplitScreenEnabled = false; m_bIntroRunning = false; m_eGameMode = eMode_Singleplayer; - // m_bInterfaceRenderingOff = false; - // m_bHandRenderingOff = false; m_bTutorialMode = false; - m_disconnectReason = DisconnectPacket::eDisconnect_None; - m_bLiveLinkRequired = false; - m_bChangingSessionType = false; - m_bReallyChangingSessionType = false; - // memset(m_PreviewBuffer, 0, sizeof(XSOCIAL_PREVIEWIMAGE)*XUSER_MAX_COUNT); - - // m_xuidNotch moved to SkinManager - - memset(&m_InviteData, 0, sizeof(JoinFromInviteData)); - - // m_bRead_TMS_XUIDS_XML=false; - // m_bRead_TMS_DLCINFO_XML=false; - - m_pDLCFileBuffer = nullptr; - m_dwDLCFileSize = 0; - m_bDefaultCapeInstallAttempted = false; - m_bDLCInstallProcessCompleted = false; - m_bDLCInstallPending = false; - m_iTotalDLC = 0; - m_iTotalDLCInstalled = 0; mfTrialPausedTime = 0.0f; - m_bNewDLCAvailable = false; - m_bSeenNewDLCTip = false; - - m_uiGameHostSettings = 0; - #if defined(_LARGE_WORLDS) m_GameNewWorldSize = 0; m_bGameNewWorldSizeUseMoat = false; m_GameNewHellScale = 0; #endif - memset(m_playerColours, 0, MINECRAFT_NET_MAX_PLAYERS); - - m_iDLCOfferC = 0; - m_bAllDLCContentRetrieved = true; - m_bAllTMSContentRetrieved = true; - m_bTickTMSDLCFiles = true; m_bResetNether = false; LocaleAndLanguageInit(); @@ -237,1609 +185,39 @@ const wchar_t* Game::GetString(int iID) { return app.m_localizationManager.getString(iID); } -void Game::SetAction(int iPad, eXuiAction action, void* param) { - if ((m_eXuiAction[iPad] == eAppAction_ReloadTexturePack) && - (action == eAppAction_EthernetDisconnected)) { - app.DebugPrintf( - "Invalid change of App action for pad %d from %d to %d, ignoring\n", - iPad, m_eXuiAction[iPad], action); - } else if ((m_eXuiAction[iPad] == eAppAction_ReloadTexturePack) && - (action == eAppAction_ExitWorld)) { - app.DebugPrintf( - "Invalid change of App action for pad %d from %d to %d, ignoring\n", - iPad, m_eXuiAction[iPad], action); - } else if (m_eXuiAction[iPad] == eAppAction_ExitWorldCapturedThumbnail && - action != eAppAction_Idle) { - app.DebugPrintf( - "Invalid change of App action for pad %d from %d to %d, ignoring\n", - iPad, m_eXuiAction[iPad], action); - } else { - app.DebugPrintf("Changing App action for pad %d from %d to %d\n", iPad, - m_eXuiAction[iPad], action); - m_eXuiAction[iPad] = action; - m_eXuiActionParam[iPad] = param; - } -} +// SetAction moved to MenuController +// HandleButtonPresses moved to GameSettingsManager bool Game::IsAppPaused() { return m_bIsAppPaused; } void Game::SetAppPaused(bool val) { m_bIsAppPaused = val; } -void Game::HandleButtonPresses() { - for (int i = 0; i < 4; i++) { - HandleButtonPresses(i); - } -} +// Load*Menu methods moved to MenuController -void Game::HandleButtonPresses(int iPad) { - // // test an update of the profile data - // void *pData=ProfileManager.GetGameDefinedProfileData(iPad); - // - // unsigned char *pchData= (unsigned char *)pData; - // int iCount=0; - // for(int i=0;i player, - bool bNavigateBack) { - bool success = true; - - InventoryScreenInput* initData = new InventoryScreenInput(); - initData->player = player; - initData->bNavigateBack = bNavigateBack; - initData->iPad = iPad; - - if (app.GetLocalPlayerCount() > 1) { - initData->bSplitscreen = true; - success = ui.NavigateToScene(iPad, eUIScene_InventoryMenu, initData); - } else { - initData->bSplitscreen = false; - success = ui.NavigateToScene(iPad, eUIScene_InventoryMenu, initData); - } - - return success; -} - -bool Game::LoadCreativeMenu(int iPad, - std::shared_ptr player, - bool bNavigateBack) { - bool success = true; - - InventoryScreenInput* initData = new InventoryScreenInput(); - initData->player = player; - initData->bNavigateBack = bNavigateBack; - initData->iPad = iPad; - - if (app.GetLocalPlayerCount() > 1) { - initData->bSplitscreen = true; - success = ui.NavigateToScene(iPad, eUIScene_CreativeMenu, initData); - } else { - initData->bSplitscreen = false; - success = ui.NavigateToScene(iPad, eUIScene_CreativeMenu, initData); - } - - return success; -} - -bool Game::LoadCrafting2x2Menu(int iPad, - std::shared_ptr player) { - bool success = true; - - CraftingPanelScreenInput* initData = new CraftingPanelScreenInput(); - initData->player = player; - initData->iContainerType = RECIPE_TYPE_2x2; - initData->iPad = iPad; - initData->x = 0; - initData->y = 0; - initData->z = 0; - - if (app.GetLocalPlayerCount() > 1) { - initData->bSplitscreen = true; - success = ui.NavigateToScene(iPad, eUIScene_Crafting2x2Menu, initData); - } else { - initData->bSplitscreen = false; - success = ui.NavigateToScene(iPad, eUIScene_Crafting2x2Menu, initData); - } - - return success; -} - -bool Game::LoadCrafting3x3Menu(int iPad, - std::shared_ptr player, - int x, int y, int z) { - bool success = true; - - CraftingPanelScreenInput* initData = new CraftingPanelScreenInput(); - initData->player = player; - initData->iContainerType = RECIPE_TYPE_3x3; - initData->iPad = iPad; - initData->x = x; - initData->y = y; - initData->z = z; - - if (app.GetLocalPlayerCount() > 1) { - initData->bSplitscreen = true; - success = ui.NavigateToScene(iPad, eUIScene_Crafting3x3Menu, initData); - } else { - initData->bSplitscreen = false; - success = ui.NavigateToScene(iPad, eUIScene_Crafting3x3Menu, initData); - } - - return success; -} - -bool Game::LoadFireworksMenu(int iPad, - std::shared_ptr player, - int x, int y, int z) { - bool success = true; - - FireworksScreenInput* initData = new FireworksScreenInput(); - initData->player = player; - initData->iPad = iPad; - initData->x = x; - initData->y = y; - initData->z = z; - - if (app.GetLocalPlayerCount() > 1) { - initData->bSplitscreen = true; - success = ui.NavigateToScene(iPad, eUIScene_FireworksMenu, initData); - } else { - initData->bSplitscreen = false; - success = ui.NavigateToScene(iPad, eUIScene_FireworksMenu, initData); - } - - return success; -} - -bool Game::LoadEnchantingMenu(int iPad, - std::shared_ptr inventory, - int x, int y, int z, Level* level, - const std::wstring& name) { - bool success = true; - - EnchantingScreenInput* initData = new EnchantingScreenInput(); - initData->inventory = inventory; - initData->level = level; - initData->x = x; - initData->y = y; - initData->z = z; - initData->iPad = iPad; - initData->name = name; - - if (app.GetLocalPlayerCount() > 1) { - initData->bSplitscreen = true; - success = ui.NavigateToScene(iPad, eUIScene_EnchantingMenu, initData); - } else { - initData->bSplitscreen = false; - success = ui.NavigateToScene(iPad, eUIScene_EnchantingMenu, initData); - } - - return success; -} - -bool Game::LoadFurnaceMenu( - int iPad, std::shared_ptr inventory, - std::shared_ptr furnace) { - bool success = true; - - FurnaceScreenInput* initData = new FurnaceScreenInput(); - - initData->furnace = furnace; - initData->inventory = inventory; - initData->iPad = iPad; - - // Load the scene. - if (app.GetLocalPlayerCount() > 1) { - initData->bSplitscreen = true; - success = ui.NavigateToScene(iPad, eUIScene_FurnaceMenu, initData); - } else { - initData->bSplitscreen = false; - success = ui.NavigateToScene(iPad, eUIScene_FurnaceMenu, initData); - } - - return success; -} - -bool Game::LoadBrewingStandMenu( - int iPad, std::shared_ptr inventory, - std::shared_ptr brewingStand) { - bool success = true; - - BrewingScreenInput* initData = new BrewingScreenInput(); - - initData->brewingStand = brewingStand; - initData->inventory = inventory; - initData->iPad = iPad; - - // Load the scene. - if (app.GetLocalPlayerCount() > 1) { - initData->bSplitscreen = true; - success = ui.NavigateToScene(iPad, eUIScene_BrewingStandMenu, initData); - } else { - initData->bSplitscreen = false; - success = ui.NavigateToScene(iPad, eUIScene_BrewingStandMenu, initData); - } - - return success; -} - -bool Game::LoadContainerMenu(int iPad, - std::shared_ptr inventory, - std::shared_ptr container) { - bool success = true; - - ContainerScreenInput* initData = new ContainerScreenInput(); - - initData->inventory = inventory; - initData->container = container; - initData->iPad = iPad; - - // Load the scene. - if (app.GetLocalPlayerCount() > 1) { - initData->bSplitscreen = true; - - bool bLargeChest = - (initData->container->getContainerSize() > 3 * 9) ? true : false; - if (bLargeChest) { - success = - ui.NavigateToScene(iPad, eUIScene_LargeContainerMenu, initData); - } else { - success = - ui.NavigateToScene(iPad, eUIScene_ContainerMenu, initData); - } - } else { - initData->bSplitscreen = false; - success = ui.NavigateToScene(iPad, eUIScene_ContainerMenu, initData); - } - - return success; -} - -bool Game::LoadTrapMenu(int iPad, std::shared_ptr inventory, - std::shared_ptr trap) { - bool success = true; - - TrapScreenInput* initData = new TrapScreenInput(); - - initData->inventory = inventory; - initData->trap = trap; - initData->iPad = iPad; - - // Load the scene. - if (app.GetLocalPlayerCount() > 1) { - initData->bSplitscreen = true; - success = ui.NavigateToScene(iPad, eUIScene_DispenserMenu, initData); - } else { - initData->bSplitscreen = false; - success = ui.NavigateToScene(iPad, eUIScene_DispenserMenu, initData); - } - - return success; -} - -bool Game::LoadSignEntryMenu(int iPad, - std::shared_ptr sign) { - bool success = true; - - SignEntryScreenInput* initData = new SignEntryScreenInput(); - - initData->sign = sign; - initData->iPad = iPad; - - success = ui.NavigateToScene(iPad, eUIScene_SignEntryMenu, initData); - - delete initData; - - return success; -} - -bool Game::LoadRepairingMenu(int iPad, - std::shared_ptr inventory, - Level* level, int x, int y, int z) { - bool success = true; - - AnvilScreenInput* initData = new AnvilScreenInput(); - initData->inventory = inventory; - initData->level = level; - initData->x = x; - initData->y = y; - initData->z = z; - initData->iPad = iPad; - if (app.GetLocalPlayerCount() > 1) - initData->bSplitscreen = true; - else - initData->bSplitscreen = false; - - success = ui.NavigateToScene(iPad, eUIScene_AnvilMenu, initData); - - return success; -} - -bool Game::LoadTradingMenu(int iPad, - std::shared_ptr inventory, - std::shared_ptr trader, - Level* level, const std::wstring& name) { - bool success = true; - - TradingScreenInput* initData = new TradingScreenInput(); - initData->inventory = inventory; - initData->trader = trader; - initData->level = level; - initData->iPad = iPad; - if (app.GetLocalPlayerCount() > 1) - initData->bSplitscreen = true; - else - initData->bSplitscreen = false; - - success = ui.NavigateToScene(iPad, eUIScene_TradingMenu, initData); - - return success; -} - -bool Game::LoadHopperMenu(int iPad, - std::shared_ptr inventory, - std::shared_ptr hopper) { - bool success = true; - - HopperScreenInput* initData = new HopperScreenInput(); - initData->inventory = inventory; - initData->hopper = hopper; - initData->iPad = iPad; - if (app.GetLocalPlayerCount() > 1) - initData->bSplitscreen = true; - else - initData->bSplitscreen = false; - - success = ui.NavigateToScene(iPad, eUIScene_HopperMenu, initData); - - return success; -} - -bool Game::LoadHopperMenu(int iPad, - std::shared_ptr inventory, - std::shared_ptr hopper) { - bool success = true; - - HopperScreenInput* initData = new HopperScreenInput(); - initData->inventory = inventory; - initData->hopper = std::dynamic_pointer_cast(hopper); - initData->iPad = iPad; - if (app.GetLocalPlayerCount() > 1) - initData->bSplitscreen = true; - else - initData->bSplitscreen = false; - - success = ui.NavigateToScene(iPad, eUIScene_HopperMenu, initData); - - return success; -} - -bool Game::LoadHorseMenu(int iPad, - std::shared_ptr inventory, - std::shared_ptr container, - std::shared_ptr horse) { - bool success = true; - - HorseScreenInput* initData = new HorseScreenInput(); - initData->inventory = inventory; - initData->container = container; - initData->horse = horse; - initData->iPad = iPad; - if (app.GetLocalPlayerCount() > 1) - initData->bSplitscreen = true; - else - initData->bSplitscreen = false; - - success = ui.NavigateToScene(iPad, eUIScene_HorseMenu, initData); - - return success; -} - -bool Game::LoadBeaconMenu(int iPad, - std::shared_ptr inventory, - std::shared_ptr beacon) { - bool success = true; - - BeaconScreenInput* initData = new BeaconScreenInput(); - initData->inventory = inventory; - initData->beacon = beacon; - initData->iPad = iPad; - if (app.GetLocalPlayerCount() > 1) - initData->bSplitscreen = true; - else - initData->bSplitscreen = false; - - success = ui.NavigateToScene(iPad, eUIScene_BeaconMenu, initData); - - return success; -} ////////////////////////////////////////////// // GAME SETTINGS ////////////////////////////////////////////// -void Game::InitGameSettings() { - for (int i = 0; i < XUSER_MAX_COUNT; i++) { - GameSettingsA[i] = - (GAME_SETTINGS*)ProfileManager.GetGameDefinedProfileData(i); - // clear the flag to say the settings have changed - GameSettingsA[i]->bSettingsChanged = false; - // SetDefaultGameSettings(i); - done on a callback from the profile - // manager - // 4J-PB - adding in for Windows & PS3 to set the defaults for the - // joypad -#if defined(_WINDOWS64) - C_4JProfile::PROFILESETTINGS* pProfileSettings = - ProfileManager.GetDashboardProfileSettings(i); - // clear this for now - it will come from reading the system values - memset(pProfileSettings, 0, sizeof(C_4JProfile::PROFILESETTINGS)); - SetDefaultOptions(pProfileSettings, i); -#else - // 4jcrqaft: Linux (and any other platform): profile data is - // zero-initialised, so explicitly apply defaults - C_4JProfile::PROFILESETTINGS* pProfileSettings = - ProfileManager.GetDashboardProfileSettings(i); - memset(pProfileSettings, 0, sizeof(C_4JProfile::PROFILESETTINGS)); - SetDefaultOptions(pProfileSettings, i); -#endif - } -} -int Game::SetDefaultOptions(C_4JProfile::PROFILESETTINGS* pSettings, - const int iPad) { - SetGameSettings(iPad, eGameSetting_MusicVolume, DEFAULT_VOLUME_LEVEL); - SetGameSettings(iPad, eGameSetting_SoundFXVolume, DEFAULT_VOLUME_LEVEL); - SetGameSettings(iPad, eGameSetting_Gamma, 50); - // 4J-PB - Don't reset the difficult level if we're in-game - if (Minecraft::GetInstance()->level == nullptr) { - app.DebugPrintf("SetDefaultOptions - Difficulty = 1\n"); - SetGameSettings(iPad, eGameSetting_Difficulty, 1); - } - SetGameSettings(iPad, eGameSetting_Sensitivity_InGame, 100); - SetGameSettings(iPad, eGameSetting_ViewBob, 1); - SetGameSettings(iPad, eGameSetting_ControlScheme, 0); - SetGameSettings(iPad, eGameSetting_ControlInvertLook, - (pSettings->iYAxisInversion != 0) ? 1 : 0); - SetGameSettings(iPad, eGameSetting_ControlSouthPaw, - pSettings->bSwapSticks ? 1 : 0); - SetGameSettings(iPad, eGameSetting_SplitScreenVertical, 0); - SetGameSettings(iPad, eGameSetting_GamertagsVisible, 1); - // Interim TU 1.6.6 - SetGameSettings(iPad, eGameSetting_Sensitivity_InMenu, 100); - SetGameSettings(iPad, eGameSetting_DisplaySplitscreenGamertags, 1); - SetGameSettings(iPad, eGameSetting_Hints, 1); - SetGameSettings(iPad, eGameSetting_Autosave, 2); - SetGameSettings(iPad, eGameSetting_Tooltips, 1); - SetGameSettings(iPad, eGameSetting_InterfaceOpacity, 80); - - // TU 5 - SetGameSettings(iPad, eGameSetting_Clouds, 1); - SetGameSettings(iPad, eGameSetting_Online, 1); - SetGameSettings(iPad, eGameSetting_InviteOnly, 0); - SetGameSettings(iPad, eGameSetting_FriendsOfFriends, 1); - - // default the update changes message to zero - // 4J-PB - We'll only display the message if the profile is pre-TU5 - // SetGameSettings(iPad,eGameSetting_DisplayUpdateMessage,0); - - // TU 6 - SetGameSettings(iPad, eGameSetting_BedrockFog, 0); - SetGameSettings(iPad, eGameSetting_DisplayHUD, 1); - SetGameSettings(iPad, eGameSetting_DisplayHand, 1); - - // TU 7 - SetGameSettings(iPad, eGameSetting_CustomSkinAnim, 1); - - // TU 9 - SetGameSettings(iPad, eGameSetting_DeathMessages, 1); - SetGameSettings(iPad, eGameSetting_UISize, 1); - SetGameSettings(iPad, eGameSetting_UISizeSplitscreen, 2); - SetGameSettings(iPad, eGameSetting_AnimatedCharacter, 1); - - // TU 12 - GameSettingsA[iPad]->ucCurrentFavoriteSkinPos = 0; - for (int i = 0; i < MAX_FAVORITE_SKINS; i++) { - GameSettingsA[iPad]->uiFavoriteSkinA[i] = 0xFFFFFFFF; - } - - // TU 13 - GameSettingsA[iPad]->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - - // 1.6.4 - app.SetGameHostOption(eGameHostOption_MobGriefing, 1); - app.SetGameHostOption(eGameHostOption_KeepInventory, 0); - app.SetGameHostOption(eGameHostOption_DoMobSpawning, 1); - app.SetGameHostOption(eGameHostOption_DoMobLoot, 1); - app.SetGameHostOption(eGameHostOption_DoTileDrops, 1); - app.SetGameHostOption(eGameHostOption_NaturalRegeneration, 1); - app.SetGameHostOption(eGameHostOption_DoDaylightCycle, 1); - - // 4J-PB - leave these in, or remove from everywhere they are referenced! - // Although probably best to leave in unless we split the profile settings - // into platform specific classes - having different meaning per platform - // for the same bitmask could get confusing - // #ifdef 0 - // PS3DEC13 - SetGameSettings(iPad, eGameSetting_PS3_EULA_Read, 0); // EULA not read - - // PS3 1.05 - added Greek - - // 4J-JEV: We cannot change these in-game, as they could affect localised - // strings and font. XB1: Fix for #172947 - Content: Gameplay: While playing - // in language different form system default one and resetting options to - // their defaults in active gameplay causes in-game language to change and - // HUD to disappear - if (!app.GetGameStarted()) { - GameSettingsA[iPad]->ucLanguage = - MINECRAFT_LANGUAGE_DEFAULT; // use the system language - GameSettingsA[iPad]->ucLocale = - MINECRAFT_LANGUAGE_DEFAULT; // use the system locale - } - - // #endif - - return 0; -} - -int Game::DefaultOptionsCallback( - void* pParam, C_4JProfile::PROFILESETTINGS* pSettings, const int iPad) { - Game* pApp = (Game*)pParam; - - // flag the default options to be set - - pApp->DebugPrintf("Setting default options for player %d", iPad); - pApp->SetAction(iPad, eAppAction_SetDefaultOptions, (void*)pSettings); - // pApp->SetDefaultOptions(pSettings,iPad); - - // if the profile data has been changed, then force a profile write - // It seems we're allowed to break the 5 minute rule if it's the result of a - // user action - // pApp->CheckGameSettingsChanged(); - - return 0; -} - -int Game::OldProfileVersionCallback(void* pParam, - unsigned char* pucData, - const unsigned short usVersion, - const int iPad) { - // check what needs to be done with this version to update to the current - // one - - switch (usVersion) { - case PROFILE_VERSION_8: { - GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; - // reset the display new message counter - pGameSettings->uiBitmaskValues |= - GAMESETTING_DISPLAYUPDATEMSG; // eGameSetting_DisplayUpdateMessage - // (counter) - - // Added a bitmask in TU13 to enable/disable display of the Mash-up - // pack worlds in the saves list - pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - - // PS3DEC13 - pGameSettings->uiBitmaskValues &= - ~GAMESETTING_PS3EULAREAD; // eGameSetting_PS3_EULA_Read - off - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = - MINECRAFT_LANGUAGE_DEFAULT; // use the system language - - } break; - case PROFILE_VERSION_9: - // PS3DEC13 - { - GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; - pGameSettings->uiBitmaskValues |= - GAMESETTING_DISPLAYUPDATEMSG; // eGameSetting_DisplayUpdateMessage - // (counter) - pGameSettings->uiBitmaskValues &= - ~GAMESETTING_PS3EULAREAD; // eGameSetting_PS3_EULA_Read - - // off - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = - MINECRAFT_LANGUAGE_DEFAULT; // use the system language - } - break; - case PROFILE_VERSION_10: { - GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; - pGameSettings->uiBitmaskValues |= - GAMESETTING_DISPLAYUPDATEMSG; // eGameSetting_DisplayUpdateMessage - // (counter) - pGameSettings->ucLanguage = - MINECRAFT_LANGUAGE_DEFAULT; // use the system language - } break; - case PROFILE_VERSION_11: { - GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; - pGameSettings->uiBitmaskValues |= - GAMESETTING_DISPLAYUPDATEMSG; // eGameSetting_DisplayUpdateMessage - // (counter) - } break; - case PROFILE_VERSION_12: { - GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; - pGameSettings->uiBitmaskValues |= - GAMESETTING_DISPLAYUPDATEMSG; // eGameSetting_DisplayUpdateMessage - // (counter) - } break; - default: { - // This might be from a version during testing of new profile - // updates - app.DebugPrintf( - "Don't know what to do with this profile version!\n"); - - GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; - pGameSettings->ucMenuSensitivity = - 100; // eGameSetting_Sensitivity_InMenu - pGameSettings->ucInterfaceOpacity = - 80; // eGameSetting_Sensitivity_InMenu - pGameSettings->usBitmaskValues |= - 0x0200; // eGameSetting_DisplaySplitscreenGamertags - on - pGameSettings->usBitmaskValues |= 0x0400; // eGameSetting_Hints - - // on - pGameSettings->usBitmaskValues |= - 0x1000; // eGameSetting_Autosave - 2 - pGameSettings->usBitmaskValues |= - 0x8000; // eGameSetting_Tooltips - on - - pGameSettings->uiBitmaskValues = 0L; // reset - pGameSettings->uiBitmaskValues |= - GAMESETTING_CLOUDS; // eGameSetting_Clouds - on - pGameSettings->uiBitmaskValues |= - GAMESETTING_ONLINE; // eGameSetting_GameSetting_Online - on - // eGameSetting_GameSetting_Invite - off - pGameSettings->uiBitmaskValues |= - GAMESETTING_FRIENDSOFFRIENDS; // eGameSetting_GameSetting_FriendsOfFriends - // - on - pGameSettings->uiBitmaskValues |= - GAMESETTING_DISPLAYUPDATEMSG; // eGameSetting_DisplayUpdateMessage - // (counter) - pGameSettings->uiBitmaskValues &= - ~GAMESETTING_BEDROCKFOG; // eGameSetting_BedrockFog - off - pGameSettings->uiBitmaskValues |= - GAMESETTING_DISPLAYHUD; // eGameSetting_DisplayHUD - on - pGameSettings->uiBitmaskValues |= - GAMESETTING_DISPLAYHAND; // eGameSetting_DisplayHand - on - pGameSettings->uiBitmaskValues |= - GAMESETTING_CUSTOMSKINANIM; // eGameSetting_CustomSkinAnim - on - pGameSettings->uiBitmaskValues |= - GAMESETTING_DEATHMESSAGES; // eGameSetting_DeathMessages - on - pGameSettings->uiBitmaskValues |= - (GAMESETTING_UISIZE & 0x00000800); // uisize 2 - pGameSettings->uiBitmaskValues |= - (GAMESETTING_UISIZE_SPLITSCREEN & - 0x00004000); // splitscreen ui size 3 - pGameSettings->uiBitmaskValues |= - GAMESETTING_ANIMATEDCHARACTER; // eGameSetting_AnimatedCharacter - // - on - // TU12 - // favorite skins added, but only set in TU12 - set to FFs - for (int i = 0; i < MAX_FAVORITE_SKINS; i++) { - pGameSettings->uiFavoriteSkinA[i] = 0xFFFFFFFF; - } - pGameSettings->ucCurrentFavoriteSkinPos = 0; - // Added a bitmask in TU13 to enable/disable display of the Mash-up - // pack worlds in the saves list - pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - - // PS3DEC13 - pGameSettings->uiBitmaskValues &= - ~GAMESETTING_PS3EULAREAD; // eGameSetting_PS3_EULA_Read - off - - // PS3 1.05 - added Greek - pGameSettings->ucLanguage = - MINECRAFT_LANGUAGE_DEFAULT; // use the system language - - } break; - } - - return 0; -} - -void Game::ApplyGameSettingsChanged(int iPad) { - ActionGameSettings(iPad, eGameSetting_MusicVolume); - ActionGameSettings(iPad, eGameSetting_SoundFXVolume); - ActionGameSettings(iPad, eGameSetting_Gamma); - ActionGameSettings(iPad, eGameSetting_Difficulty); - ActionGameSettings(iPad, eGameSetting_Sensitivity_InGame); - ActionGameSettings(iPad, eGameSetting_ViewBob); - ActionGameSettings(iPad, eGameSetting_ControlScheme); - ActionGameSettings(iPad, eGameSetting_ControlInvertLook); - ActionGameSettings(iPad, eGameSetting_ControlSouthPaw); - ActionGameSettings(iPad, eGameSetting_SplitScreenVertical); - ActionGameSettings(iPad, eGameSetting_GamertagsVisible); - - // Interim TU 1.6.6 - ActionGameSettings(iPad, eGameSetting_Sensitivity_InMenu); - ActionGameSettings(iPad, eGameSetting_DisplaySplitscreenGamertags); - ActionGameSettings(iPad, eGameSetting_Hints); - ActionGameSettings(iPad, eGameSetting_InterfaceOpacity); - ActionGameSettings(iPad, eGameSetting_Tooltips); - - ActionGameSettings(iPad, eGameSetting_Clouds); - ActionGameSettings(iPad, eGameSetting_BedrockFog); - ActionGameSettings(iPad, eGameSetting_DisplayHUD); - ActionGameSettings(iPad, eGameSetting_DisplayHand); - ActionGameSettings(iPad, eGameSetting_CustomSkinAnim); - ActionGameSettings(iPad, eGameSetting_DeathMessages); - ActionGameSettings(iPad, eGameSetting_UISize); - ActionGameSettings(iPad, eGameSetting_UISizeSplitscreen); - ActionGameSettings(iPad, eGameSetting_AnimatedCharacter); - - ActionGameSettings(iPad, eGameSetting_PS3_EULA_Read); -} - -void Game::ActionGameSettings(int iPad, eGameSetting eVal) { - Minecraft* pMinecraft = Minecraft::GetInstance(); - switch (eVal) { - case eGameSetting_MusicVolume: - if (iPad == ProfileManager.GetPrimaryPad()) { - pMinecraft->options->set( - Options::Option::MUSIC, - ((float)GameSettingsA[iPad]->ucMusicVolume) / 100.0f); - } - break; - case eGameSetting_SoundFXVolume: - if (iPad == ProfileManager.GetPrimaryPad()) { - pMinecraft->options->set( - Options::Option::SOUND, - ((float)GameSettingsA[iPad]->ucSoundFXVolume) / 100.0f); - } - break; - case eGameSetting_Gamma: - if (iPad == ProfileManager.GetPrimaryPad()) { - // ucGamma range is 0-100, UpdateGamma is 0 - 32768 - float fVal = ((float)GameSettingsA[iPad]->ucGamma) * 327.68f; - RenderManager.UpdateGamma((unsigned short)fVal); - } - - break; - case eGameSetting_Difficulty: - if (iPad == ProfileManager.GetPrimaryPad()) { - pMinecraft->options->toggle( - Options::Option::DIFFICULTY, - GameSettingsA[iPad]->usBitmaskValues & 0x03); - app.DebugPrintf("Difficulty toggle to %d\n", - GameSettingsA[iPad]->usBitmaskValues & 0x03); - - // Update the Game Host setting - app.SetGameHostOption(eGameHostOption_Difficulty, - pMinecraft->options->difficulty); - - // send this to the other players if we are in-game - bool bInGame = pMinecraft->level != nullptr; - - // Game Host only (and for now we can't change the diff while in - // game, so this shouldn't happen) - if (bInGame && g_NetworkManager.IsHost() && - (iPad == ProfileManager.GetPrimaryPad())) { - app.SetXuiServerAction( - iPad, eXuiServerAction_ServerSettingChanged_Difficulty); - } - } else { - app.DebugPrintf( - "NOT ACTIONING DIFFICULTY - Primary pad is %d, This pad is " - "%d\n", - ProfileManager.GetPrimaryPad(), iPad); - } - - break; - case eGameSetting_Sensitivity_InGame: - // 4J-PB - we don't use the options value - // tell the input that we've changed the sensitivity - range of the - // slider is 0 to 200, default is 100 - pMinecraft->options->set( - Options::Option::SENSITIVITY, - ((float)GameSettingsA[iPad]->ucSensitivity) / 100.0f); - // InputManager.SetJoypadSensitivity(iPad,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f); - - break; - case eGameSetting_ViewBob: - // 4J-PB - not handled here any more - it's read from the - // gamesettings per player - // pMinecraft->options->toggle(Options::Option::VIEW_BOBBING,GameSettingsA[iPad]->usBitmaskValues&0x04); - break; - case eGameSetting_ControlScheme: - InputManager.SetJoypadMapVal( - iPad, (GameSettingsA[iPad]->usBitmaskValues & 0x30) >> 4); - break; - - case eGameSetting_ControlInvertLook: - // Nothing specific to do for this setting. - break; - - case eGameSetting_ControlSouthPaw: - // What is the setting? - if (GameSettingsA[iPad]->usBitmaskValues & 0x80) { - // Southpaw. - InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_LX, - AXIS_MAP_RX); - InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_LY, - AXIS_MAP_RY); - InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_RX, - AXIS_MAP_LX); - InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_RY, - AXIS_MAP_LY); - InputManager.SetJoypadStickTriggerMap(iPad, TRIGGER_MAP_0, - TRIGGER_MAP_1); - InputManager.SetJoypadStickTriggerMap(iPad, TRIGGER_MAP_1, - TRIGGER_MAP_0); - } else { - // Right handed. - InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_LX, - AXIS_MAP_LX); - InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_LY, - AXIS_MAP_LY); - InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_RX, - AXIS_MAP_RX); - InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_RY, - AXIS_MAP_RY); - InputManager.SetJoypadStickTriggerMap(iPad, TRIGGER_MAP_0, - TRIGGER_MAP_0); - InputManager.SetJoypadStickTriggerMap(iPad, TRIGGER_MAP_1, - TRIGGER_MAP_1); - } - break; - case eGameSetting_SplitScreenVertical: - if (iPad == ProfileManager.GetPrimaryPad()) { - pMinecraft->updatePlayerViewportAssignments(); - } - break; - case eGameSetting_GamertagsVisible: { - bool bInGame = pMinecraft->level != nullptr; - - // Game Host only - if (bInGame && g_NetworkManager.IsHost() && - (iPad == ProfileManager.GetPrimaryPad())) { - // Update the Game Host setting if you are the host and you are - // in-game - app.SetGameHostOption( - eGameHostOption_Gamertags, - ((GameSettingsA[iPad]->usBitmaskValues & 0x0008) != 0) ? 1 - : 0); - app.SetXuiServerAction( - iPad, eXuiServerAction_ServerSettingChanged_Gamertags); - - PlayerList* players = - MinecraftServer::getInstance()->getPlayerList(); - for (auto it3 = players->players.begin(); - it3 != players->players.end(); ++it3) { - std::shared_ptr decorationPlayer = *it3; - decorationPlayer->setShowOnMaps( - (app.GetGameHostOption(eGameHostOption_Gamertags) != 0) - ? true - : false); - } - } - } break; - // Interim TU 1.6.6 - case eGameSetting_Sensitivity_InMenu: - // 4J-PB - we don't use the options value - // tell the input that we've changed the sensitivity - range of the - // slider is 0 to 200, default is 100 - // pMinecraft->options->set(Options::Option::SENSITIVITY,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f); - // InputManager.SetJoypadSensitivity(iPad,((float)GameSettingsA[iPad]->ucSensitivity)/100.0f); - - break; - - case eGameSetting_DisplaySplitscreenGamertags: - for (std::uint8_t idx = 0; idx < XUSER_MAX_COUNT; ++idx) { - if (pMinecraft->localplayers[idx] != nullptr) { - if (pMinecraft->localplayers[idx]->m_iScreenSection == - C4JRender::VIEWPORT_TYPE_FULLSCREEN) { - ui.DisplayGamertag(idx, false); - } else { - ui.DisplayGamertag(idx, true); - } - } - } - - break; - case eGameSetting_InterfaceOpacity: - // update the tooltips display - ui.RefreshTooltips(iPad); - - break; - case eGameSetting_Hints: - // nothing to do here - break; - case eGameSetting_Tooltips: - if ((GameSettingsA[iPad]->usBitmaskValues & 0x8000) != 0) { - ui.SetEnableTooltips(iPad, true); - } else { - ui.SetEnableTooltips(iPad, false); - } - break; - case eGameSetting_Clouds: - // nothing to do here - break; - case eGameSetting_Online: - // nothing to do here - break; - case eGameSetting_InviteOnly: - // nothing to do here - break; - case eGameSetting_FriendsOfFriends: - // nothing to do here - break; - case eGameSetting_BedrockFog: { - bool bInGame = pMinecraft->level != nullptr; - - // Game Host only - if (bInGame && g_NetworkManager.IsHost() && - (iPad == ProfileManager.GetPrimaryPad())) { - // Update the Game Host setting if you are the host and you are - // in-game - app.SetGameHostOption( - eGameHostOption_BedrockFog, - GetGameSettings(iPad, eGameSetting_BedrockFog) ? 1 : 0); - app.SetXuiServerAction( - iPad, eXuiServerAction_ServerSettingChanged_BedrockFog); - } - } break; - case eGameSetting_DisplayHUD: - // nothing to do here - break; - case eGameSetting_DisplayHand: - // nothing to do here - break; - case eGameSetting_CustomSkinAnim: - // nothing to do here - break; - case eGameSetting_DeathMessages: - // nothing to do here - break; - case eGameSetting_UISize: - // nothing to do here - break; - case eGameSetting_UISizeSplitscreen: - // nothing to do here - break; - case eGameSetting_AnimatedCharacter: - // nothing to do here - break; - case eGameSetting_PS3_EULA_Read: - // nothing to do here - break; - case eGameSetting_PSVita_NetworkModeAdhoc: - // nothing to do here - break; - default: - break; - } -} // Skin/Cape/FavoriteSkin methods moved to SkinManager // Mash-up pack worlds -void Game::HideMashupPackWorld(int iPad, unsigned int iMashupPackID) { - unsigned int uiPackID = iMashupPackID - 1024; // mash-up ids start at 1024 - GameSettingsA[iPad]->uiMashUpPackWorldsDisplay &= ~(1 << uiPackID); - GameSettingsA[iPad]->bSettingsChanged = true; -} -void Game::EnableMashupPackWorlds(int iPad) { - GameSettingsA[iPad]->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; - GameSettingsA[iPad]->bSettingsChanged = true; -} -unsigned int Game::GetMashupPackWorlds(int iPad) { - return GameSettingsA[iPad]->uiMashUpPackWorldsDisplay; -} -void Game::SetMinecraftLanguage(int iPad, unsigned char ucLanguage) { - GameSettingsA[iPad]->ucLanguage = ucLanguage; - GameSettingsA[iPad]->bSettingsChanged = true; -} -unsigned char Game::GetMinecraftLanguage(int iPad) { - // if there are no game settings read yet, return the default language - if (GameSettingsA[iPad] == nullptr) { - return 0; - } else { - return GameSettingsA[iPad]->ucLanguage; - } -} -void Game::SetMinecraftLocale(int iPad, unsigned char ucLocale) { - GameSettingsA[iPad]->ucLocale = ucLocale; - GameSettingsA[iPad]->bSettingsChanged = true; -} -unsigned char Game::GetMinecraftLocale(int iPad) { - // if there are no game settings read yet, return the default language - if (GameSettingsA[iPad] == nullptr) { - return 0; - } else { - return GameSettingsA[iPad]->ucLocale; - } -} -void Game::SetGameSettings(int iPad, eGameSetting eVal, - unsigned char ucVal) { - // Minecraft *pMinecraft=Minecraft::GetInstance(); - switch (eVal) { - case eGameSetting_MusicVolume: - if (GameSettingsA[iPad]->ucMusicVolume != ucVal) { - GameSettingsA[iPad]->ucMusicVolume = ucVal; - if (iPad == ProfileManager.GetPrimaryPad()) { - ActionGameSettings(iPad, eVal); - } - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_SoundFXVolume: - if (GameSettingsA[iPad]->ucSoundFXVolume != ucVal) { - GameSettingsA[iPad]->ucSoundFXVolume = ucVal; - if (iPad == ProfileManager.GetPrimaryPad()) { - ActionGameSettings(iPad, eVal); - } - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_Gamma: - if (GameSettingsA[iPad]->ucGamma != ucVal) { - GameSettingsA[iPad]->ucGamma = ucVal; - if (iPad == ProfileManager.GetPrimaryPad()) { - ActionGameSettings(iPad, eVal); - } - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_Difficulty: - if ((GameSettingsA[iPad]->usBitmaskValues & 0x03) != - (ucVal & 0x03)) { - GameSettingsA[iPad]->usBitmaskValues &= ~0x03; - GameSettingsA[iPad]->usBitmaskValues |= ucVal & 0x03; - if (iPad == ProfileManager.GetPrimaryPad()) { - ActionGameSettings(iPad, eVal); - } - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_Sensitivity_InGame: - if (GameSettingsA[iPad]->ucSensitivity != ucVal) { - GameSettingsA[iPad]->ucSensitivity = ucVal; - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_ViewBob: - if ((GameSettingsA[iPad]->usBitmaskValues & 0x0004) != - ((ucVal & 0x01) << 2)) { - if (ucVal != 0) { - GameSettingsA[iPad]->usBitmaskValues |= 0x0004; - } else { - GameSettingsA[iPad]->usBitmaskValues &= ~0x0004; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_ControlScheme: // bits 5 and 6 - if ((GameSettingsA[iPad]->usBitmaskValues & 0x30) != - ((ucVal & 0x03) << 4)) { - GameSettingsA[iPad]->usBitmaskValues &= ~0x0030; - if (ucVal != 0) { - GameSettingsA[iPad]->usBitmaskValues |= (ucVal & 0x03) << 4; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_ControlInvertLook: - if ((GameSettingsA[iPad]->usBitmaskValues & 0x0040) != - ((ucVal & 0x01) << 6)) { - if (ucVal != 0) { - GameSettingsA[iPad]->usBitmaskValues |= 0x0040; - } else { - GameSettingsA[iPad]->usBitmaskValues &= ~0x0040; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_ControlSouthPaw: - if ((GameSettingsA[iPad]->usBitmaskValues & 0x0080) != - ((ucVal & 0x01) << 7)) { - if (ucVal != 0) { - GameSettingsA[iPad]->usBitmaskValues |= 0x0080; - } else { - GameSettingsA[iPad]->usBitmaskValues &= ~0x0080; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_SplitScreenVertical: - if ((GameSettingsA[iPad]->usBitmaskValues & 0x0100) != - ((ucVal & 0x01) << 8)) { - if (ucVal != 0) { - GameSettingsA[iPad]->usBitmaskValues |= 0x0100; - } else { - GameSettingsA[iPad]->usBitmaskValues &= ~0x0100; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_GamertagsVisible: - if ((GameSettingsA[iPad]->usBitmaskValues & 0x0008) != - ((ucVal & 0x01) << 3)) { - if (ucVal != 0) { - GameSettingsA[iPad]->usBitmaskValues |= 0x0008; - } else { - GameSettingsA[iPad]->usBitmaskValues &= ~0x0008; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - // 4J-PB - Added for Interim TU for 1.6.6 - case eGameSetting_Sensitivity_InMenu: - if (GameSettingsA[iPad]->ucMenuSensitivity != ucVal) { - GameSettingsA[iPad]->ucMenuSensitivity = ucVal; - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_DisplaySplitscreenGamertags: - if ((GameSettingsA[iPad]->usBitmaskValues & 0x0200) != - ((ucVal & 0x01) << 9)) { - if (ucVal != 0) { - GameSettingsA[iPad]->usBitmaskValues |= 0x0200; - } else { - GameSettingsA[iPad]->usBitmaskValues &= ~0x0200; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_Hints: - if ((GameSettingsA[iPad]->usBitmaskValues & 0x0400) != - ((ucVal & 0x01) << 10)) { - if (ucVal != 0) { - GameSettingsA[iPad]->usBitmaskValues |= 0x0400; - } else { - GameSettingsA[iPad]->usBitmaskValues &= ~0x0400; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_Autosave: - if ((GameSettingsA[iPad]->usBitmaskValues & 0x7800) != - ((ucVal & 0x0F) << 11)) { - GameSettingsA[iPad]->usBitmaskValues &= ~0x7800; - if (ucVal != 0) { - GameSettingsA[iPad]->usBitmaskValues |= (ucVal & 0x0F) - << 11; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - - case eGameSetting_Tooltips: - if ((GameSettingsA[iPad]->usBitmaskValues & 0x8000) != - ((ucVal & 0x01) << 15)) { - if (ucVal != 0) { - GameSettingsA[iPad]->usBitmaskValues |= 0x8000; - } else { - GameSettingsA[iPad]->usBitmaskValues &= ~0x8000; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_InterfaceOpacity: - if (GameSettingsA[iPad]->ucInterfaceOpacity != ucVal) { - GameSettingsA[iPad]->ucInterfaceOpacity = ucVal; - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - - break; - case eGameSetting_Clouds: - if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CLOUDS) != - (ucVal & 0x01)) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_CLOUDS; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_CLOUDS; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - - break; - - case eGameSetting_Online: - if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_ONLINE) != - (ucVal & 0x01) << 1) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_ONLINE; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_ONLINE; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - - break; - case eGameSetting_InviteOnly: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_INVITEONLY) != (ucVal & 0x01) << 2) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= - GAMESETTING_INVITEONLY; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_INVITEONLY; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - - break; - case eGameSetting_FriendsOfFriends: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_FRIENDSOFFRIENDS) != (ucVal & 0x01) << 3) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= - GAMESETTING_FRIENDSOFFRIENDS; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_FRIENDSOFFRIENDS; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - - break; - case eGameSetting_DisplayUpdateMessage: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_DISPLAYUPDATEMSG) != (ucVal & 0x03) << 4) { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_DISPLAYUPDATEMSG; - if (ucVal > 0) { - GameSettingsA[iPad]->uiBitmaskValues |= (ucVal & 0x03) << 4; - } - - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - - break; - - case eGameSetting_BedrockFog: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_BEDROCKFOG) != (ucVal & 0x01) << 6) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= - GAMESETTING_BEDROCKFOG; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_BEDROCKFOG; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - - break; - case eGameSetting_DisplayHUD: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_DISPLAYHUD) != (ucVal & 0x01) << 7) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= - GAMESETTING_DISPLAYHUD; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_DISPLAYHUD; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - - break; - case eGameSetting_DisplayHand: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_DISPLAYHAND) != (ucVal & 0x01) << 8) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= - GAMESETTING_DISPLAYHAND; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_DISPLAYHAND; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - - break; - - case eGameSetting_CustomSkinAnim: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_CUSTOMSKINANIM) != (ucVal & 0x01) << 9) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= - GAMESETTING_CUSTOMSKINANIM; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_CUSTOMSKINANIM; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - - break; - // TU9 - case eGameSetting_DeathMessages: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_DEATHMESSAGES) != (ucVal & 0x01) << 10) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= - GAMESETTING_DEATHMESSAGES; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_DEATHMESSAGES; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_UISize: - if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_UISIZE) != - ((ucVal & 0x03) << 11)) { - GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_UISIZE; - if (ucVal != 0) { - GameSettingsA[iPad]->uiBitmaskValues |= (ucVal & 0x03) - << 11; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_UISizeSplitscreen: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_UISIZE_SPLITSCREEN) != ((ucVal & 0x03) << 13)) { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_UISIZE_SPLITSCREEN; - if (ucVal != 0) { - GameSettingsA[iPad]->uiBitmaskValues |= (ucVal & 0x03) - << 13; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_AnimatedCharacter: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_ANIMATEDCHARACTER) != (ucVal & 0x01) << 15) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= - GAMESETTING_ANIMATEDCHARACTER; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_ANIMATEDCHARACTER; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_PS3_EULA_Read: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_PS3EULAREAD) != (ucVal & 0x01) << 16) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= - GAMESETTING_PS3EULAREAD; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_PS3EULAREAD; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - case eGameSetting_PSVita_NetworkModeAdhoc: - if ((GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_PSVITANETWORKMODEADHOC) != (ucVal & 0x01) << 17) { - if (ucVal == 1) { - GameSettingsA[iPad]->uiBitmaskValues |= - GAMESETTING_PSVITANETWORKMODEADHOC; - } else { - GameSettingsA[iPad]->uiBitmaskValues &= - ~GAMESETTING_PSVITANETWORKMODEADHOC; - } - ActionGameSettings(iPad, eVal); - GameSettingsA[iPad]->bSettingsChanged = true; - } - break; - } -} - -unsigned char Game::GetGameSettings(eGameSetting eVal) { - int iPad = ProfileManager.GetPrimaryPad(); - - return GetGameSettings(iPad, eVal); -} - -unsigned char Game::GetGameSettings(int iPad, eGameSetting eVal) { - switch (eVal) { - case eGameSetting_MusicVolume: - return GameSettingsA[iPad]->ucMusicVolume; - break; - case eGameSetting_SoundFXVolume: - return GameSettingsA[iPad]->ucSoundFXVolume; - break; - case eGameSetting_Gamma: - return GameSettingsA[iPad]->ucGamma; - break; - case eGameSetting_Difficulty: - return GameSettingsA[iPad]->usBitmaskValues & 0x0003; - break; - case eGameSetting_Sensitivity_InGame: - return GameSettingsA[iPad]->ucSensitivity; - break; - case eGameSetting_ViewBob: - return ((GameSettingsA[iPad]->usBitmaskValues & 0x0004) >> 2); - break; - case eGameSetting_GamertagsVisible: - return ((GameSettingsA[iPad]->usBitmaskValues & 0x0008) >> 3); - break; - case eGameSetting_ControlScheme: - return ((GameSettingsA[iPad]->usBitmaskValues & 0x0030) >> - 4); // 2 bits - break; - case eGameSetting_ControlInvertLook: - return ((GameSettingsA[iPad]->usBitmaskValues & 0x0040) >> 6); - break; - case eGameSetting_ControlSouthPaw: - return ((GameSettingsA[iPad]->usBitmaskValues & 0x0080) >> 7); - break; - case eGameSetting_SplitScreenVertical: - return ((GameSettingsA[iPad]->usBitmaskValues & 0x0100) >> 8); - break; - // 4J-PB - Added for Interim TU for 1.6.6 - case eGameSetting_Sensitivity_InMenu: - return GameSettingsA[iPad]->ucMenuSensitivity; - break; - - case eGameSetting_DisplaySplitscreenGamertags: - return ((GameSettingsA[iPad]->usBitmaskValues & 0x0200) >> 9); - break; - - case eGameSetting_Hints: - return ((GameSettingsA[iPad]->usBitmaskValues & 0x0400) >> 10); - break; - case eGameSetting_Autosave: { - unsigned char ucVal = - (GameSettingsA[iPad]->usBitmaskValues & 0x7800) >> 11; - return ucVal; - } break; - case eGameSetting_Tooltips: - return ((GameSettingsA[iPad]->usBitmaskValues & 0x8000) >> 15); - break; - - case eGameSetting_InterfaceOpacity: - return GameSettingsA[iPad]->ucInterfaceOpacity; - break; - - case eGameSetting_Clouds: - return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CLOUDS); - break; - case eGameSetting_Online: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_ONLINE) >> - 1; - break; - case eGameSetting_InviteOnly: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_INVITEONLY) >> - 2; - break; - case eGameSetting_FriendsOfFriends: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_FRIENDSOFFRIENDS) >> - 3; - break; - case eGameSetting_DisplayUpdateMessage: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_DISPLAYUPDATEMSG) >> - 4; - break; - case eGameSetting_BedrockFog: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_BEDROCKFOG) >> - 6; - break; - case eGameSetting_DisplayHUD: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_DISPLAYHUD) >> - 7; - break; - case eGameSetting_DisplayHand: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_DISPLAYHAND) >> - 8; - break; - case eGameSetting_CustomSkinAnim: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_CUSTOMSKINANIM) >> - 9; - break; - // TU9 - case eGameSetting_DeathMessages: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_DEATHMESSAGES) >> - 10; - break; - case eGameSetting_UISize: { - unsigned char ucVal = - (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_UISIZE) >> - 11; - return ucVal; - } break; - case eGameSetting_UISizeSplitscreen: { - unsigned char ucVal = (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_UISIZE_SPLITSCREEN) >> - 13; - return ucVal; - } break; - case eGameSetting_AnimatedCharacter: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_ANIMATEDCHARACTER) >> - 15; - - case eGameSetting_PS3_EULA_Read: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_PS3EULAREAD) >> - 16; - - case eGameSetting_PSVita_NetworkModeAdhoc: - return (GameSettingsA[iPad]->uiBitmaskValues & - GAMESETTING_PSVITANETWORKMODEADHOC) >> - 17; - } - return 0; -} - -void Game::CheckGameSettingsChanged(bool bOverride5MinuteTimer, - int iPad) { - // If the settings have changed, write them to the profile - - if (iPad == XUSER_INDEX_ANY) { - for (int i = 0; i < XUSER_MAX_COUNT; i++) { - if (GameSettingsA[i]->bSettingsChanged) { - ProfileManager.WriteToProfile(i, true, bOverride5MinuteTimer); - GameSettingsA[i]->bSettingsChanged = false; - } - } - } else { - if (GameSettingsA[iPad]->bSettingsChanged) { - ProfileManager.WriteToProfile(iPad, true, bOverride5MinuteTimer); - GameSettingsA[iPad]->bSettingsChanged = false; - } - } -} - -void Game::ClearGameSettingsChangedFlag(int iPad) { - GameSettingsA[iPad]->bSettingsChanged = false; -} /////////////////////////// // @@ -1847,168 +225,16 @@ void Game::ClearGameSettingsChangedFlag(int iPad) { // //////////////////////////// #if !defined(_DEBUG_MENUS_ENABLED) -unsigned int Game::GetGameSettingsDebugMask( - int iPad, bool bOverridePlayer) // bOverridePlayer is to force the send for - // the server to get the read options -{ - return 0; -} -void Game::SetGameSettingsDebugMask(int iPad, unsigned int uiVal) {} -void Game::ActionDebugMask(int iPad, bool bSetAllClear) {} #else -unsigned int Game::GetGameSettingsDebugMask( - int iPad, bool bOverridePlayer) // bOverridePlayer is to force the send for - // the server to get the read options -{ - if (iPad == -1) { - iPad = ProfileManager.GetPrimaryPad(); - } - if (iPad < 0) iPad = 0; - std::shared_ptr player = - Minecraft::GetInstance()->localplayers[iPad]; - if (bOverridePlayer || player == nullptr) { - return GameSettingsA[iPad]->uiDebugBitmask; - } else { - return player->GetDebugOptions(); - } -} - -void Game::SetGameSettingsDebugMask(int iPad, unsigned int uiVal) { -#if !defined(_CONTENT_PACKAGE) - GameSettingsA[iPad]->bSettingsChanged = true; - GameSettingsA[iPad]->uiDebugBitmask = uiVal; - - // update the value so the network server can use it - std::shared_ptr player = - Minecraft::GetInstance()->localplayers[iPad]; - - if (player) { - Minecraft::GetInstance()->localgameModes[iPad]->handleDebugOptions( - uiVal, player); - } -#endif -} - -void Game::ActionDebugMask(int iPad, bool bSetAllClear) { - unsigned int ulBitmask = app.GetGameSettingsDebugMask(iPad); - - if (bSetAllClear) ulBitmask = 0L; - - // these settings should only be actioned for the primary player - if (ProfileManager.GetPrimaryPad() != iPad) return; - - for (int i = 0; i < eDebugSetting_Max; i++) { - switch (i) { - case eDebugSetting_LoadSavesFromDisk: - if (ulBitmask & (1 << i)) { - app.SetLoadSavesFromFolderEnabled(true); - } else { - app.SetLoadSavesFromFolderEnabled(false); - } - break; - - case eDebugSetting_WriteSavesToDisk: - if (ulBitmask & (1 << i)) { - app.SetWriteSavesToFolderEnabled(true); - } else { - app.SetWriteSavesToFolderEnabled(false); - } - break; - - case eDebugSetting_FreezePlayers: // eDebugSetting_InterfaceOff: - if (ulBitmask & (1 << i)) { - app.SetFreezePlayers(true); - - // Turn off interface rendering. - // app.SetInterfaceRenderingOff( true ); - } else { - app.SetFreezePlayers(false); - - // Turn on interface rendering. - // app.SetInterfaceRenderingOff( false ); - } - break; - case eDebugSetting_Safearea: - if (ulBitmask & (1 << i)) { - app.ShowSafeArea(true); - } else { - app.ShowSafeArea(false); - } - break; - - // case eDebugSetting_HandRenderingOff: - // if(ulBitmask&(1<iPad, actionInfo->action); -} void Game::HandleXuiActions(void) { eXuiAction eAction; @@ -2042,7 +268,7 @@ void Game::HandleXuiActions(void) { // are there any app actions to deal with? for (int i = 0; i < XUSER_MAX_COUNT; i++) { eAction = app.GetXuiAction(i); - param = m_eXuiActionParam[i]; + param = m_menuController.getXuiActionParam(i); if (eAction != eAppAction_Idle) { switch (eAction) { @@ -3431,10 +1657,21 @@ void Game::HandleXuiActions(void) { } } +// loadMediaArchive and loadStringTable moved to ArchiveManager/LocalizationManager + + + + + + + + + + + int Game::BannedLevelDialogReturned( void* pParam, int iPad, const C4JStorage::EMessageResult result) { Game* pApp = (Game*)pParam; - // Minecraft *pMinecraft=Minecraft::GetInstance(); if (result == C4JStorage::EMessage_ResultAccept) { } else { @@ -3447,449 +1684,6 @@ int Game::BannedLevelDialogReturned( return 0; } -// loadMediaArchive and loadStringTable moved to ArchiveManager/LocalizationManager - -int Game::PrimaryPlayerSignedOutReturned( - void* pParam, int iPad, const C4JStorage::EMessageResult) { - // Game* pApp = (Game*)pParam; - // Minecraft *pMinecraft=Minecraft::GetInstance(); - - // if the player is null, we're in the menus - // if(Minecraft::GetInstance()->player!=nullptr) - - // We always create a session before kicking of any of the game code, so - // even though we may still be joining/creating a game at this point we want - // to handle it differently from just being in a menu - if (g_NetworkManager.IsInSession()) { - app.SetAction(iPad, eAppAction_PrimaryPlayerSignedOutReturned); - } else { - app.SetAction(iPad, eAppAction_PrimaryPlayerSignedOutReturned_Menus); - } - return 0; -} - -int Game::EthernetDisconnectReturned( - void* pParam, int iPad, const C4JStorage::EMessageResult) { - // Game* pApp = (Game*)pParam; - Minecraft* pMinecraft = Minecraft::GetInstance(); - - // if the player is null, we're in the menus - if (Minecraft::GetInstance()->player != nullptr) { - app.SetAction(pMinecraft->player->GetXboxPad(), - eAppAction_EthernetDisconnectedReturned); - } else { - // 4J-PB - turn off the PSN store icon just in case this happened when - // we were in one of the DLC menus - app.SetAction(iPad, eAppAction_EthernetDisconnectedReturned_Menus); - } - return 0; -} - -int Game::SignoutExitWorldThreadProc(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(); - - // app.SetGameStarted(false); - - 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); - // 4J - Force a disconnection, this handles the situation that the - // server has already disconnected - 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(); - } - - // 4J Stu - This only does something if we actually have a server, so - // don't need to do any other checks - MinecraftServer::HaltServer(true); - - // We need to call the stats & leaderboards save before we exit the - // session - // pMinecraft->forceStatsSave(); - saveStats = false; - - // 4J Stu - Leave the session once the disconnect packet has been sent - 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); - - // 4J-JEV: Fix for #106402 - TCR #014 BAS Debug Output: - // TU12: Mass Effect Mash-UP: Save file "Default_DisplayName" is created on - // all storage devices after signing out from a re-launched pre-generated - // world - app.m_gameRules.unloadCurrentGameRules(); // - - MinecraftServer::resetFlags(); - - // We can't start/join a new game until the session is destroyed, so wait - // for it to be idle again - while (g_NetworkManager.IsInSession()) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - - return 0; -} - -int Game::UnlockFullInviteReturned(void* pParam, int iPad, - C4JStorage::EMessageResult result) { - // Game* pApp = (Game*)pParam; - Minecraft* pMinecraft = Minecraft::GetInstance(); - bool bNoPlayer; - - // bug 11285 - TCR 001: BAS Game Stability: CRASH - When trying to join a - // full version game with a trial version, the trial crashes 4J-PB - we may - // be in the main menus here, and we don't have a pMinecraft->player - - if (pMinecraft->player == nullptr) { - bNoPlayer = true; - } - - return 0; -} - -int Game::UnlockFullSaveReturned(void* pParam, int iPad, - C4JStorage::EMessageResult result) { - return 0; -} - -int Game::UnlockFullExitReturned(void* pParam, int iPad, - C4JStorage::EMessageResult result) { - Game* pApp = (Game*)pParam; - Minecraft* pMinecraft = Minecraft::GetInstance(); - - if (result != C4JStorage::EMessage_ResultAccept) { - pApp->SetAction(pMinecraft->player->GetXboxPad(), - eAppAction_ExitWorldTrial); - } - - return 0; -} - -int Game::TrialOverReturned(void* pParam, int iPad, - C4JStorage::EMessageResult result) { - Game* pApp = (Game*)pParam; - Minecraft* pMinecraft = Minecraft::GetInstance(); - - if (result != C4JStorage::EMessage_ResultAccept) { - pApp->SetAction(pMinecraft->player->GetXboxPad(), eAppAction_ExitTrial); - } - - return 0; -} - -void Game::ProfileReadErrorCallback(void* pParam) { - Game* pApp = (Game*)pParam; - int iPrimaryPlayer = ProfileManager.GetPrimaryPad(); - pApp->SetAction(iPrimaryPlayer, eAppAction_ProfileReadError); -} - -void Game::ClearSignInChangeUsersMask() { - // 4J-PB - When in the main menu, the user is on pad 0, and any change they - // make to their profile will be to pad 0 data If they then go in as a - // secondary player to a splitscreen game, their profile will not be read - // again on pad 1 if they were previously in a splitscreen game This is - // because m_uiLastSignInData remembers they were in previously, and doesn't - // read the profile data for them again Fix this by resetting the - // m_uiLastSignInData on pressing play game for secondary users. The Primary - // user does a read profile on play game anyway - int iPrimaryPlayer = ProfileManager.GetPrimaryPad(); - - if (m_uiLastSignInData != 0) { - if (iPrimaryPlayer >= 0) { - m_uiLastSignInData = 1 << iPrimaryPlayer; - } else { - m_uiLastSignInData = 0; - } - } -} -void Game::SignInChangeCallback(void* pParam, - bool bPrimaryPlayerChanged, - unsigned int uiSignInData) { - Game* pApp = (Game*)pParam; - // check if the primary player signed out - int iPrimaryPlayer = ProfileManager.GetPrimaryPad(); - - if ((ProfileManager.GetLockedProfile() != -1) && iPrimaryPlayer != -1) { - if (((uiSignInData & (1 << iPrimaryPlayer)) == 0) || - bPrimaryPlayerChanged) { - // Primary Player gone or there's been a sign out and sign in of the - // primary player, so kick them out - pApp->SetAction(iPrimaryPlayer, eAppAction_PrimaryPlayerSignedOut); - - // 4J-PB - invalidate their banned level list - pApp->InvalidateBannedList(iPrimaryPlayer); - - // need to ditch any DLCOffers info - StorageManager.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 (ProfileManager.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_currentSigninInfo[i].dwGuestNumber != 0 && - guestNumber != 0 && - pApp->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, ProfileManager.GetPrimaryPad()); - } - - // 4J Stu - On PS4 we can also cause to exit players if they are - // signed out here, but we shouldn't do that if we are going to - // switch to an offline game as it will likely crash due to - // incompatible parallel processes - bool switchToOffline = false; - // If it's an online game, and the primary profile is no longer - // signed into LIVE then we act as if disconnected - if (!ProfileManager.IsSignedInLive( - ProfileManager.GetLockedProfile()) && - !g_NetworkManager.IsLocalGame()) { - switchToOffline = true; - } - - // printf("Old: %x, New: %x, Changed: %x\n", m_ulLastSignInData, - // ulSignInData, changedPlayers); - for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) { - // Primary player shouldn't be subjected to these checks, - // and shouldn't call ExitPlayer - if (i == iPrimaryPlayer) continue; - - // A guest a signed in or out, out of order which - // invalidates all the guest players we have in the game - if (hasGuestIdChanged && - pApp->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); - // 4J Stu - Also need to detect the case where the sign - // in mask is the same, but the player has swapped users - // (eg still signed in but xuid different) Fix for - // #48451 - TU5: Code: UI: Splitscreen: Title crashes - // when switching to a profile previously signed out via - // splitscreen profile selection - - // 4J-PB - compiler complained about if below ('&&' - // within '||') - making it easier to read - bool bPlayerChanged = - (uiChangedPlayers & (1 << i)) == (1 << i); - bool bPlayerSignedIn = ((uiSignInData & (1 << i)) != 0); - - if (bPlayerChanged && - (!bPlayerSignedIn || - (bPlayerSignedIn && - !ProfileManager.AreXUIDSEqual( - pApp->m_currentSigninInfo[i].xuid, - info.xuid)))) { - // 4J-PB - invalidate their banned level list - pApp->DebugPrintf( - "Player at index %d Left - invalidating their " - "banned list\n", - i); - pApp->InvalidateBannedList(i); - - // 4J-HG: If either the player is in the network - // manager or in the game, need to exit player - // TODO: Do we need to check the network manager? - 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 it's an online game, and the primary profile is no longer - // signed into LIVE then we act as if disconnected - if (switchToOffline) { - pApp->SetAction(iPrimaryPlayer, - eAppAction_EthernetDisconnected); - } - - g_NetworkManager.HandleSignInChange(); - } - // Some menus require the player to be signed in to live, so if this - // callback happens and the primary player is no longer signed in - // then nav back - else if (pApp->GetLiveLinkRequired() && - !ProfileManager.IsSignedInLive( - ProfileManager.GetLockedProfile())) { - { - pApp->SetAction(iPrimaryPlayer, - eAppAction_EthernetDisconnected); - } - } - } - m_uiLastSignInData = uiSignInData; - } else if (iPrimaryPlayer != -1) { - // make sure the TMS banned list data is ditched - the player may have - // gone in to help & options, backed out, and signed out - pApp->InvalidateBannedList(iPrimaryPlayer); - - // need to ditch any DLCOffers info - StorageManager.ClearDLCOffers(); - pApp->ClearAndResetDLCDownloadQueue(); - pApp->ClearDLCInstalled(); - } - - // Update the guest numbers to the current state - for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) { - if (FAILED(XUserGetSigninInfo(i, - XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY, - &pApp->m_currentSigninInfo[i]))) { - pApp->m_currentSigninInfo[i].xuid = INVALID_XUID; - pApp->m_currentSigninInfo[i].dwGuestNumber = 0; - } - app.DebugPrintf("Player at index %d has guest number %d\n", i, - pApp->m_currentSigninInfo[i].dwGuestNumber); - } -} - -void Game::NotificationsCallback(void* pParam, - std::uint32_t dwNotification, - unsigned int uiParam) { - Game* pClass = (Game*)pParam; - - // push these on to the notifications to be handled in qnet's dowork - - 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 (!InputManager.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: - // Need to inform xuis that we've possibly had DLC installed - { - // app.m_dlcManager.SetNeedsUpdated(true); - // Clear the DLC installed flag to cause a GetDLC to run if - // it's called - app.ClearDLCInstalled(); - - ui.HandleDLCInstalled(ProfileManager.GetPrimaryPad()); - } - break; - case XN_SYS_STORAGEDEVICESCHANGED: { - } break; - } - - pClass->m_vNotifications.push_back(pNotification); -} #if defined(_DEBUG_MENUS_ENABLED) bool Game::DebugArtToolsOn() { @@ -3928,100 +1722,10 @@ int Game::GetLocalPlayerCount(void) { return iPlayerC; } -int Game::MarketplaceCountsCallback( - void* pParam, C4JStorage::DLC_TMS_DETAILS* pTMSDetails, int iPad) { - app.DebugPrintf("Marketplace Counts= New - %d Total - %d\n", - pTMSDetails->dwNewOffers, pTMSDetails->dwTotalOffers); - if (pTMSDetails->dwNewOffers > 0) { - app.m_bNewDLCAvailable = true; - app.m_bSeenNewDLCTip = false; - } else { - app.m_bNewDLCAvailable = false; - app.m_bSeenNewDLCTip = true; - } - - return 0; -} - -bool Game::StartInstallDLCProcess(int iPad) { - app.DebugPrintf("--- Game::StartInstallDLCProcess: pad=%i.\n", - iPad); - - // If there is already a call to this in progress, then do nothing - // If the app says dlc is installed, then there has been no new system - // message to tell us there's new DLC since the last call to - // StartInstallDLCProcess - if ((app.DLCInstallProcessCompleted() == false) && - (m_bDLCInstallPending == false)) { - app.m_dlcManager.resetUnnamedCorruptCount(); - m_bDLCInstallPending = true; - m_iTotalDLC = 0; - m_iTotalDLCInstalled = 0; - app.DebugPrintf( - "--- Game::StartInstallDLCProcess - " - "StorageManager.GetInstalledDLC\n"); - - StorageManager.GetInstalledDLC( - iPad, [this](int iInstalledC, int pad) { - return dlcInstalledCallback(iInstalledC, pad); - }); - return true; - } else { - app.DebugPrintf( - "--- Game::StartInstallDLCProcess - nothing to do\n"); - - return false; - } -} // Installed DLC callback -int Game::dlcInstalledCallback(int iInstalledC, int iPad) { - DebugPrintf( - "--- Game::dlcInstalledCallback: totalDLC=%i, pad=%i.\n", - iInstalledC, iPad); - m_iTotalDLC = iInstalledC; - MountNextDLC(iPad); - return 0; -} -void Game::MountNextDLC(int iPad) { - app.DebugPrintf("--- Game::MountNextDLC: pad=%i.\n", iPad); - if (m_iTotalDLCInstalled < m_iTotalDLC) { - // Mount it - // We also need to match the ones the user wants to mount with the - // installed DLC We're supposed to use a generic save game as a cache of - // these to do this, with XUSER_ANY - - if (StorageManager.MountInstalledDLC( - iPad, m_iTotalDLCInstalled, - [this](int pad, std::uint32_t dwErr, - std::uint32_t dwLicenceMask) { - return dlcMountedCallback(pad, dwErr, dwLicenceMask); - }) != ERROR_IO_PENDING) { - // corrupt DLC - app.DebugPrintf("Failed to mount DLC %d for pad %d\n", - m_iTotalDLCInstalled, iPad); - ++m_iTotalDLCInstalled; - app.MountNextDLC(iPad); - } else { - app.DebugPrintf("StorageManager.MountInstalledDLC ok\n"); - } - } else { - /* Removed - now loading these on demand instead of as each pack is - mounted if(m_iTotalDLCInstalled > 0) - { - Minecraft *pMinecraft=Minecraft::GetInstance(); - pMinecraft->levelRenderer->AddDLCSkinsToMemTextures(); - } - */ - - m_bDLCInstallPending = false; - m_bDLCInstallProcessCompleted = true; - - ui.HandleDLCMountingComplete(); - } -} // 4J-JEV: For the sake of clarity in DLCMountedCallback. #if defined(_WINDOWS64) @@ -4030,68 +1734,6 @@ void Game::MountNextDLC(int iPad) { #define CONTENT_DATA_DISPLAY_NAME(a) (a.wszDisplayName) #endif -int Game::dlcMountedCallback(int iPad, std::uint32_t dwErr, - std::uint32_t dwLicenceMask) { -#if defined(_WINDOWS64) - DebugPrintf("--- Game::dlcMountedCallback\n"); - - if (dwErr != ERROR_SUCCESS) { - // corrupt DLC - app.DebugPrintf("Failed to mount DLC for pad %d: %u\n", iPad, dwErr); - app.m_dlcManager.incrementUnnamedCorruptCount(); - } else { - XCONTENT_DATA ContentData = - StorageManager.GetDLC(app.m_iTotalDLCInstalled); - - DLCPack* pack = - app.m_dlcManager.getPack(CONTENT_DATA_DISPLAY_NAME(ContentData)); - - if (pack != nullptr && pack->IsCorrupt()) { - app.DebugPrintf( - "Pack '%ls' is corrupt, removing it from the DLC Manager.\n", - CONTENT_DATA_DISPLAY_NAME(ContentData)); - - app.m_dlcManager.removePack(pack); - pack = nullptr; - } - - if (pack == nullptr) { - app.DebugPrintf("Pack \"%ls\" is not installed, so adding it\n", - CONTENT_DATA_DISPLAY_NAME(ContentData)); - -#if defined(_WINDOWS64) - pack = new DLCPack(ContentData.szDisplayName, dwLicenceMask); -#else - pack = new DLCPack(ContentData.wszDisplayName, dwLicenceMask); -#endif - pack->SetDLCMountIndex(app.m_iTotalDLCInstalled); - pack->SetDLCDeviceID(ContentData.DeviceID); - app.m_dlcManager.addPack(pack); - - app.HandleDLC(pack); - - if (pack->getDLCItemsCount(DLCManager::e_DLCType_Texture) > 0) { - Minecraft::GetInstance()->skins->addTexturePackFromDLC( - pack, pack->GetPackId()); - } - } else { - app.DebugPrintf( - "Pack \"%ls\" is already installed. Updating license to %u\n", - CONTENT_DATA_DISPLAY_NAME(ContentData), dwLicenceMask); - - pack->SetDLCMountIndex(app.m_iTotalDLCInstalled); - pack->SetDLCDeviceID(ContentData.DeviceID); - pack->updateLicenseMask(dwLicenceMask); - } - - StorageManager.UnmountInstalledDLC(); - } - ++app.m_iTotalDLCInstalled; - app.MountNextDLC(iPad); - -#endif - return 0; -} #undef CONTENT_DATA_DISPLAY_NAME // void Game::InstallDefaultCape() @@ -4122,18 +1764,6 @@ int Game::dlcMountedCallback(int iPad, std::uint32_t dwErr, // } // } -void Game::HandleDLC(DLCPack* pack) { - unsigned int dwFilesProcessed = 0; -#if defined(_WINDOWS64) || defined(__linux__) - std::vector dlcFilenames; -#endif - StorageManager.GetMountedDLCFileList("DLCDrive", dlcFilenames); - for (int i = 0; i < dlcFilenames.size(); i++) { - m_dlcManager.readDLCDataFile(dwFilesProcessed, dlcFilenames[i], pack); - } - - if (dwFilesProcessed == 0) m_dlcManager.removePack(pack); -} // int Game::DLCReadCallback(void* // pParam,C4JStorage::DLC_FILE_DETAILS *pDLCData) @@ -4173,10 +1803,10 @@ void Game::UpdateTime() { } bool Game::isXuidDeadmau5(PlayerUID xuid) { - auto it = MojangData.find(xuid); // 4J Stu - The .at and [] accessors + auto it = DLCController::MojangData.find(xuid); // 4J Stu - The .at and [] accessors // insert elements if they don't exist - if (it != MojangData.end()) { - MOJANG_DATA* pMojangData = MojangData[xuid]; + if (it != DLCController::MojangData.end()) { + MOJANG_DATA* pMojangData = DLCController::MojangData[xuid]; if (pMojangData && pMojangData->eXuid == eXUID_Deadmau5) { return true; } @@ -4191,167 +1821,11 @@ void Game::ExitGame() {} // Invites -void Game::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; - // memcpy(&m_InviteData,pJoinData,sizeof(JoinFromInviteData)); - SetAction(dwUserIndex, eAppAction_ExitAndJoinFromInvite); -} -int Game::ExitAndJoinFromInvite(void* pParam, int iPad, - C4JStorage::EMessageResult result) { - Game* pApp = (Game*)pParam; - // Minecraft *pMinecraft=Minecraft::GetInstance(); - // buttons are swapped on this menu - if (result == C4JStorage::EMessage_ResultDecline) { - pApp->SetAction(iPad, eAppAction_ExitAndJoinFromInviteConfirmed); - } - return 0; -} -int Game::ExitAndJoinFromInviteSaveDialogReturned( - void* pParam, int iPad, C4JStorage::EMessageResult result) { - Game* pClass = (Game*)pParam; - // Exit with or without saving - // Decline means save in this dialog - if (result == C4JStorage::EMessage_ResultDecline || - result == C4JStorage::EMessage_ResultThirdOption) { - if (result == C4JStorage::EMessage_ResultDecline) // Save - { - // Check they have the full texture pack if they are using one - // 4J-PB - Is the player trying to save but they are using a trial - // texturepack ? - if (!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) { - TexturePack* tPack = - Minecraft::GetInstance()->skins->getSelected(); - DLCPack* pDLCPack = tPack->getDLCPack(); - if (!pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Texture, - L"")) { - // upsell - // get the dlc texture pack - - unsigned int uiIDA[2]; - uiIDA[0] = IDS_CONFIRM_OK; - uiIDA[1] = IDS_CONFIRM_CANCEL; - - // Give the player a warning about the trial version of the - // texture pack - ui.RequestErrorMessage( - IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, - IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad, - &Game::WarningTrialTexturePackReturned, - pClass); - - return 0; - } - } - // does the save exist? - bool bSaveExists; - StorageManager.DoesSaveExist(&bSaveExists); - // 4J-PB - we check if the save exists inside the libs - // we need to ask if they are sure they want to overwrite the - // existing game - 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, - ProfileManager.GetPrimaryPad(), - &Game::ExitAndJoinFromInviteAndSaveReturned, - pClass); - return 0; - } else { - MinecraftServer::getInstance()->setSaveOnExit(true); - } - } else { - // been a few requests for a confirm on exit without saving - 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, ProfileManager.GetPrimaryPad(), - &Game::ExitAndJoinFromInviteDeclineSaveReturned, - pClass); - return 0; - } - - app.SetAction(ProfileManager.GetPrimaryPad(), - eAppAction_ExitAndJoinFromInviteConfirmed); - } - return 0; -} - -int Game::WarningTrialTexturePackReturned( - void* pParam, int iPad, C4JStorage::EMessageResult result) { - // 4J Stu - I added this in when fixing an X1 bug. We should probably add - // this as well but I don't have time to test all platforms atm - - return 0; -} - -int Game::ExitAndJoinFromInviteAndSaveReturned( - void* pParam, int iPad, C4JStorage::EMessageResult result) { - // Game* pClass = (Game*)pParam; - - // results switched for this dialog - if (result == C4JStorage::EMessage_ResultDecline) { - int saveOrCheckpointId = 0; - - // Check they have the full texture pack if they are using one - // 4J-PB - Is the player trying to save but they are using a trial - // texturepack ? - if (!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) { - TexturePack* tPack = Minecraft::GetInstance()->skins->getSelected(); - - DLCPack* pDLCPack = tPack->getDLCPack(); - if (!pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Texture, - L"")) { - // upsell - // get the dlc texture pack - - unsigned int uiIDA[2]; - uiIDA[0] = IDS_CONFIRM_OK; - uiIDA[1] = IDS_CONFIRM_CANCEL; - - // Give the player a warning about the trial version of the - // texture pack - ui.RequestErrorMessage( - IDS_WARNING_DLC_TRIALTEXTUREPACK_TITLE, - IDS_WARNING_DLC_TRIALTEXTUREPACK_TEXT, uiIDA, 2, iPad, - &Game::WarningTrialTexturePackReturned, nullptr); - - return 0; - } - } - // bool validSave = - // StorageManager.GetSaveUniqueNumber(&saveOrCheckpointId); - // SentientManager.RecordLevelSaveOrCheckpoint(ProfileManager.GetPrimaryPad(), - // saveOrCheckpointId); - MinecraftServer::getInstance()->setSaveOnExit(true); - // flag a app action of exit and join game from invite - app.SetAction(iPad, eAppAction_ExitAndJoinFromInviteConfirmed); - } - return 0; -} - -int Game::ExitAndJoinFromInviteDeclineSaveReturned( - void* pParam, int iPad, C4JStorage::EMessageResult result) { - // results switched for this dialog - if (result == C4JStorage::EMessage_ResultDecline) { - MinecraftServer::getInstance()->setSaveOnExit(false); - // flag a app action of exit and join game from invite - app.SetAction(iPad, eAppAction_ExitAndJoinFromInviteConfirmed); - } - return 0; -} ////////////////////////////////////////////////////////////////////////// // @@ -4364,47 +1838,10 @@ int Game::ExitAndJoinFromInviteDeclineSaveReturned( ////////////////////////////////////////////////////////////////////////// void Game::FatalLoadError() {} -void Game::SetSpecialTutorialCompletionFlag(int iPad, int index) { - if (index >= 0 && index < 32 && GameSettingsA[iPad] != nullptr) { - GameSettingsA[iPad]->uiSpecialTutorialBitmask |= (1 << index); - } -} -void Game::AddCreditText(const wchar_t* lpStr) { - DebugPrintf("ADDING CREDIT - %ls\n", lpStr); - // add a std::string from the DLC to a credits std::vector - SCreditTextItemDef* pCreditStruct = new SCreditTextItemDef; - pCreditStruct->m_eType = eSmallText; - pCreditStruct->m_iStringID[0] = NO_TRANSLATED_STRING; - pCreditStruct->m_iStringID[1] = NO_TRANSLATED_STRING; - pCreditStruct->m_Text = new wchar_t[wcslen(lpStr) + 1]; - wcscpy((wchar_t*)pCreditStruct->m_Text, lpStr); - vDLCCredits.push_back(pCreditStruct); -} -bool Game::AlreadySeenCreditText(const std::wstring& wstemp) { - for (unsigned int i = 0; i < m_vCreditText.size(); i++) { - std::wstring temp = m_vCreditText.at(i); - // if they are the same, break out of the case - if (temp.compare(wstemp) == 0) { - return true; - } - } - - // add this text - m_vCreditText.push_back((wchar_t*)wstemp.c_str()); - return false; -} - -unsigned int Game::GetDLCCreditsCount() { - return (unsigned int)vDLCCredits.size(); -} - -SCreditTextItemDef* Game::GetDLCCredits(int iIndex) { - return vDLCCredits.at(iIndex); -} // Game Host options @@ -4413,363 +1850,13 @@ void Game::SetGameHostOption(eGameHostOption eVal, GameHostOptions::set(eVal, uiVal); } -void Game::SetGameHostOption(unsigned int& uiHostSettings, - eGameHostOption eVal, - unsigned int uiVal) { - switch (eVal) { - case eGameHostOption_FriendsOfFriends: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS; - } - break; - case eGameHostOption_Difficulty: - // clear the difficulty first - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DIFFICULTY; - uiHostSettings |= (GAME_HOST_OPTION_BITMASK_DIFFICULTY & uiVal); - break; - case eGameHostOption_Gamertags: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_GAMERTAGS; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_GAMERTAGS; - } - - break; - case eGameHostOption_GameType: - // clear the game type first - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_GAMETYPE; - uiHostSettings |= - (GAME_HOST_OPTION_BITMASK_GAMETYPE & (uiVal << 4)); - break; - case eGameHostOption_LevelType: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_LEVELTYPE; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_LEVELTYPE; - } - - break; - case eGameHostOption_Structures: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_STRUCTURES; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_STRUCTURES; - } - - break; - case eGameHostOption_BonusChest: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_BONUSCHEST; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_BONUSCHEST; - } - - break; - case eGameHostOption_HasBeenInCreative: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_BEENINCREATIVE; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_BEENINCREATIVE; - } - - break; - case eGameHostOption_PvP: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_PVP; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_PVP; - } - - break; - case eGameHostOption_TrustPlayers: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS; - } - - break; - case eGameHostOption_TNT: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_TNT; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_TNT; - } - - break; - case eGameHostOption_FireSpreads: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_FIRESPREADS; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_FIRESPREADS; - } - break; - case eGameHostOption_CheatsEnabled: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTFLY; - uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTHUNGER; - uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTFLY; - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTHUNGER; - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; - } - break; - case eGameHostOption_HostCanFly: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTFLY; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTFLY; - } - break; - case eGameHostOption_HostCanChangeHunger: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTHUNGER; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTHUNGER; - } - break; - case eGameHostOption_HostCanBeInvisible: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; - } - break; - - case eGameHostOption_BedrockFog: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_BEDROCKFOG; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_BEDROCKFOG; - } - break; - case eGameHostOption_DisableSaving: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_DISABLESAVE; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DISABLESAVE; - } - break; - case eGameHostOption_WasntSaveOwner: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_NOTOWNER; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_NOTOWNER; - } - break; - case eGameHostOption_MobGriefing: - if (uiVal != 1) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_MOBGRIEFING; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_MOBGRIEFING; - } - break; - case eGameHostOption_KeepInventory: - if (uiVal != 0) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_KEEPINVENTORY; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_KEEPINVENTORY; - } - break; - case eGameHostOption_DoMobSpawning: - if (uiVal != 1) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING; - } - break; - case eGameHostOption_DoMobLoot: - if (uiVal != 1) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBLOOT; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOMOBLOOT; - } - break; - case eGameHostOption_DoTileDrops: - if (uiVal != 1) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOTILEDROPS; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOTILEDROPS; - } - break; - case eGameHostOption_NaturalRegeneration: - if (uiVal != 1) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_NATURALREGEN; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_NATURALREGEN; - } - break; - case eGameHostOption_DoDaylightCycle: - if (uiVal != 1) { - uiHostSettings |= GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE; - } else { - // off - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE; - } - break; - case eGameHostOption_WorldSize: - // clear the difficulty first - uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_WORLDSIZE; - uiHostSettings |= - (GAME_HOST_OPTION_BITMASK_WORLDSIZE & - (uiVal << GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT)); - break; - case eGameHostOption_All: - uiHostSettings = uiVal; - break; - default: - break; - } -} unsigned int Game::GetGameHostOption(eGameHostOption eVal) { return GameHostOptions::get(eVal); } -unsigned int Game::GetGameHostOption(unsigned int uiHostSettings, - eGameHostOption eVal) { - // unsigned int uiVal=0; - switch (eVal) { - case eGameHostOption_FriendsOfFriends: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS); - break; - case eGameHostOption_Difficulty: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_DIFFICULTY); - break; - case eGameHostOption_Gamertags: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_GAMERTAGS); - break; - case eGameHostOption_GameType: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_GAMETYPE) >> 4; - break; - case eGameHostOption_All: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_ALL); - break; - case eGameHostOption_Tutorial: - // special case - tutorial is offline, but we want the gamertag - // option, and set Easy mode, structures on, fire on, tnt on, pvp - // on, trust players on - return ((uiHostSettings & GAME_HOST_OPTION_BITMASK_GAMERTAGS) | - GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS | - GAME_HOST_OPTION_BITMASK_FIRESPREADS | - GAME_HOST_OPTION_BITMASK_TNT | - GAME_HOST_OPTION_BITMASK_PVP | - GAME_HOST_OPTION_BITMASK_STRUCTURES | 1); - break; - case eGameHostOption_LevelType: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_LEVELTYPE); - break; - case eGameHostOption_Structures: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_STRUCTURES); - break; - case eGameHostOption_BonusChest: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_BONUSCHEST); - break; - case eGameHostOption_HasBeenInCreative: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_BEENINCREATIVE); - break; - case eGameHostOption_PvP: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_PVP); - break; - case eGameHostOption_TrustPlayers: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS); - break; - case eGameHostOption_TNT: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_TNT); - break; - case eGameHostOption_FireSpreads: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_FIRESPREADS); - break; - case eGameHostOption_CheatsEnabled: - return (uiHostSettings & (GAME_HOST_OPTION_BITMASK_HOSTFLY | - GAME_HOST_OPTION_BITMASK_HOSTHUNGER | - GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE)); - break; - case eGameHostOption_HostCanFly: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_HOSTFLY); - break; - case eGameHostOption_HostCanChangeHunger: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_HOSTHUNGER); - break; - case eGameHostOption_HostCanBeInvisible: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE); - break; - case eGameHostOption_BedrockFog: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_BEDROCKFOG); - break; - case eGameHostOption_DisableSaving: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_DISABLESAVE); - break; - case eGameHostOption_WasntSaveOwner: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_NOTOWNER); - case eGameHostOption_WorldSize: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_WORLDSIZE) >> - GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT; - case eGameHostOption_MobGriefing: - return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_MOBGRIEFING); - case eGameHostOption_KeepInventory: - return (uiHostSettings & GAME_HOST_OPTION_BITMASK_KEEPINVENTORY); - case eGameHostOption_DoMobSpawning: - return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING); - case eGameHostOption_DoMobLoot: - return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_DOMOBLOOT); - case eGameHostOption_DoTileDrops: - return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_DOTILEDROPS); - case eGameHostOption_NaturalRegeneration: - return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_NATURALREGEN); - case eGameHostOption_DoDaylightCycle: - return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE); - break; - default: - return 0; - } - - return false; -} -bool Game::CanRecordStatsAndAchievements() { - bool isTutorial = Minecraft::GetInstance() != nullptr && - Minecraft::GetInstance()->isTutorial(); - // 4J Stu - All of these options give the host player some advantage, so - // should not allow achievements - return !(app.GetGameHostOption(eGameHostOption_HasBeenInCreative) || - app.GetGameHostOption(eGameHostOption_HostCanBeInvisible) || - app.GetGameHostOption(eGameHostOption_HostCanChangeHunger) || - app.GetGameHostOption(eGameHostOption_HostCanFly) || - app.GetGameHostOption(eGameHostOption_WasntSaveOwner) || - !app.GetGameHostOption(eGameHostOption_MobGriefing) || - app.GetGameHostOption(eGameHostOption_KeepInventory) || - !app.GetGameHostOption(eGameHostOption_DoMobSpawning) || - (!app.GetGameHostOption(eGameHostOption_DoDaylightCycle) && - !isTutorial)); -} void Game::processSchematics(LevelChunk* levelChunk) { m_gameRules.processSchematics(levelChunk); @@ -4793,191 +1880,15 @@ const wchar_t* Game::GetGameRulesString(const std::wstring& key) { } -unsigned char Game::m_szPNG[8] = {137, 80, 78, 71, 13, 10, 26, 10}; -#define PNG_TAG_tEXt 0x74455874 - -unsigned int Game::FromBigEndian(unsigned int uiValue) { - unsigned int uiReturn = - ((uiValue >> 24) & 0x000000ff) | ((uiValue >> 8) & 0x0000ff00) | - ((uiValue << 8) & 0x00ff0000) | ((uiValue << 24) & 0xff000000); - return uiReturn; -} - -void Game::GetImageTextData(std::uint8_t* imageData, - unsigned int imageBytes, - unsigned char* seedText, - unsigned int& uiHostOptions, - bool& bHostOptionsRead, - std::uint32_t& uiTexturePack) { - auto readPngUInt32 = [](const std::uint8_t* data) -> unsigned int { - unsigned int value = 0; - std::memcpy(&value, data, sizeof(value)); - return value; - }; - - std::uint8_t* ucPtr = imageData; - unsigned int uiCount = 0; - unsigned int uiChunkLen; - unsigned int uiChunkType; - unsigned int uiCRC; - char szKeyword[80]; - - // check it's a png - for (int i = 0; i < 8; i++) { - if (m_szPNG[i] != ucPtr[i]) return; - } - - uiCount += 8; - - while (uiCount < imageBytes) { - uiChunkLen = FromBigEndian(readPngUInt32(&ucPtr[uiCount])); - uiCount += sizeof(int); - uiChunkType = FromBigEndian(readPngUInt32(&ucPtr[uiCount])); - uiCount += sizeof(int); - - if (uiChunkType == PNG_TAG_tEXt) // tEXt - { - // check that it's the 4J text - unsigned char* pszKeyword = &ucPtr[uiCount]; - while (pszKeyword < ucPtr + uiCount + uiChunkLen) { - memset(szKeyword, 0, 80); - unsigned int uiKeywordC = 0; - while (*pszKeyword != 0) { - szKeyword[uiKeywordC++] = *pszKeyword; - pszKeyword++; - } - pszKeyword++; - if (strcmp(szKeyword, "4J_SEED") == 0) { - // read the seed value - unsigned int uiValueC = 0; - while (*pszKeyword != 0 && - (pszKeyword < ucPtr + uiCount + uiChunkLen)) { - seedText[uiValueC++] = *pszKeyword; - pszKeyword++; - } - // memcpy(seedText,pszKeyword,uiChunkLen-8); - } else if (strcmp(szKeyword, "4J_HOSTOPTIONS") == 0) { - bHostOptionsRead = true; - // read the host options value - unsigned int uiValueC = 0; - unsigned char pszHostOptions[9]; // Hex representation of - // unsigned int - memset(&pszHostOptions, 0, 9); - while (*pszKeyword != 0 && - (pszKeyword < ucPtr + uiCount + uiChunkLen) && - uiValueC < 8) { - pszHostOptions[uiValueC++] = *pszKeyword; - pszKeyword++; - } - - uiHostOptions = 0; - std::stringstream ss; - ss << pszHostOptions; - ss >> std::hex >> uiHostOptions; - } else if (strcmp(szKeyword, "4J_TEXTUREPACK") == 0) { - // read the texture pack value - unsigned int uiValueC = 0; - unsigned char pszTexturePack[9]; // Hex representation of - // unsigned int - memset(&pszTexturePack, 0, 9); - while (*pszKeyword != 0 && - (pszKeyword < ucPtr + uiCount + uiChunkLen) && - uiValueC < 8) { - pszTexturePack[uiValueC++] = *pszKeyword; - pszKeyword++; - } - - std::stringstream ss; - ss << pszTexturePack; - ss >> std::hex >> uiTexturePack; - } - } - } - uiCount += uiChunkLen; - uiCRC = FromBigEndian(readPngUInt32(&ucPtr[uiCount])); - uiCount += sizeof(int); - } - - return; -} - -unsigned int Game::CreateImageTextData(std::uint8_t* textMetadata, - int64_t seed, bool hasSeed, - unsigned int uiHostOptions, - unsigned int uiTexturePackId) { - int iTextMetadataBytes = 0; - if (hasSeed) { - strcpy((char*)textMetadata, "4J_SEED"); - snprintf((char*)&textMetadata[8], 42, "%lld", (long long)seed); - - // get the length - iTextMetadataBytes += 8; - while (textMetadata[iTextMetadataBytes] != 0) iTextMetadataBytes++; - ++iTextMetadataBytes; // Add a null terminator at the end of the seed - // value - } - - // Save the host options that this world was last played with - strcpy((char*)&textMetadata[iTextMetadataBytes], "4J_HOSTOPTIONS"); - snprintf((char*)&textMetadata[iTextMetadataBytes + 15], 9, "%X", - uiHostOptions); - - iTextMetadataBytes += 15; - while (textMetadata[iTextMetadataBytes] != 0) iTextMetadataBytes++; - ++iTextMetadataBytes; // Add a null terminator at the end of the host - // options value - - // Save the texture pack id - strcpy((char*)&textMetadata[iTextMetadataBytes], "4J_TEXTUREPACK"); - snprintf((char*)&textMetadata[iTextMetadataBytes + 15], 9, "%X", - uiHostOptions); - - iTextMetadataBytes += 15; - while (textMetadata[iTextMetadataBytes] != 0) iTextMetadataBytes++; - - return iTextMetadataBytes; -} +// PNG_TAG_tEXt, FromBigEndian, GetImageTextData, CreateImageTextData moved to MenuController + + -void Game::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 Game::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 Game::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; -} std::wstring Game::getEntityName(eINSTANCEOF type) { switch (type) { @@ -5031,26 +1942,11 @@ std::wstring Game::getEntityName(eINSTANCEOF type) { return L""; } -std::uint32_t Game::m_dwContentTypeA[e_Marketplace_MAX] = { - XMARKETPLACE_OFFERING_TYPE_CONTENT, // e_DLC_SkinPack, e_DLC_TexturePacks, - // e_DLC_MashupPacks - XMARKETPLACE_OFFERING_TYPE_THEME, // e_DLC_Themes - XMARKETPLACE_OFFERING_TYPE_AVATARITEM, // e_DLC_AvatarItems - XMARKETPLACE_OFFERING_TYPE_TILE, // e_DLC_Gamerpics -}; - -int Game::TexturePackDialogReturned( - void* pParam, int iPad, C4JStorage::EMessageResult result) { - return 0; -} +// m_dwContentTypeA moved to DLCController + -std::unordered_map Game::MojangData; -std::unordered_map Game::DLCTextures_PackID; -std::unordered_map Game::DLCInfo_Trial; -std::unordered_map Game::DLCInfo_Full; -std::unordered_map Game::DLCInfo_SkinName; int32_t Game::RegisterMojangData(wchar_t* pXuidName, PlayerUID xuid, wchar_t* pSkin, wchar_t* pCape) { @@ -5077,14 +1973,14 @@ int32_t Game::RegisterMojangData(wchar_t* pXuidName, PlayerUID xuid, wcsncpy(pMojangData->wchSkin, pSkin, MAX_CAPENAME_SIZE); wcsncpy(pMojangData->wchCape, pCape, MAX_CAPENAME_SIZE); - MojangData[xuid] = pMojangData; + DLCController::MojangData[xuid] = pMojangData; } return hr; } MOJANG_DATA* Game::GetMojangDataForXuid(PlayerUID xuid) { - return MojangData[xuid]; + return DLCController::MojangData[xuid]; } int32_t Game::RegisterConfigValues(wchar_t* pType, int iValue) { @@ -5116,742 +2012,34 @@ int32_t Game::RegisterConfigValues(wchar_t* pType, int iValue) { } #if defined(_WINDOWS64) -int32_t Game::RegisterDLCData(wchar_t* pType, wchar_t* pBannerName, - int iGender, uint64_t ullOfferID_Full, - uint64_t ullOfferID_Trial, - wchar_t* pFirstSkin, - unsigned int uiSortIndex, int iConfig, - wchar_t* pDataFile) { - int32_t hr = 0; - DLC_INFO* pDLCData = new DLC_INFO; - memset(pDLCData, 0, sizeof(DLC_INFO)); - pDLCData->ullOfferID_Full = ullOfferID_Full; - pDLCData->ullOfferID_Trial = ullOfferID_Trial; - pDLCData->eDLCType = e_DLC_NotDefined; - pDLCData->iGender = iGender; - pDLCData->uiSortIndex = uiSortIndex; - pDLCData->iConfig = iConfig; - - // ignore the names if we don't recognize them - if (pBannerName != L"") { - wcsncpy_s(pDLCData->wchBanner, pBannerName, MAX_BANNERNAME_SIZE); - } - - if (pDataFile[0] != 0) { - wcsncpy_s(pDLCData->wchDataFile, pDataFile, MAX_BANNERNAME_SIZE); - } - - if (pType != nullptr) { - if (wcscmp(pType, L"Skin") == 0) { - pDLCData->eDLCType = e_DLC_SkinPack; - } else if (wcscmp(pType, L"Gamerpic") == 0) { - pDLCData->eDLCType = e_DLC_Gamerpics; - } else if (wcscmp(pType, L"Theme") == 0) { - pDLCData->eDLCType = e_DLC_Themes; - } else if (wcscmp(pType, L"Avatar") == 0) { - pDLCData->eDLCType = e_DLC_AvatarItems; - } else if (wcscmp(pType, L"MashUpPack") == 0) { - pDLCData->eDLCType = e_DLC_MashupPacks; - DLCTextures_PackID[pDLCData->iConfig] = ullOfferID_Full; - } else if (wcscmp(pType, L"TexturePack") == 0) { - pDLCData->eDLCType = e_DLC_TexturePacks; - DLCTextures_PackID[pDLCData->iConfig] = ullOfferID_Full; - } - } - - if (ullOfferID_Trial != 0ll) DLCInfo_Trial[ullOfferID_Trial] = pDLCData; - if (ullOfferID_Full != 0ll) DLCInfo_Full[ullOfferID_Full] = pDLCData; - if (pFirstSkin[0] != 0) DLCInfo_SkinName[pFirstSkin] = ullOfferID_Full; - - return hr; -} #elif defined(__linux__) -int32_t Game::RegisterDLCData(wchar_t* pType, wchar_t* pBannerName, - int iGender, uint64_t ullOfferID_Full, - uint64_t ullOfferID_Trial, - wchar_t* pFirstSkin, - unsigned int uiSortIndex, int iConfig, - wchar_t* pDataFile) { - fprintf(stderr, - "warning: Game::RegisterDLCData unimplemented for " - "platform `__linux__`\n"); - return 0; -} #else -int32_t Game::RegisterDLCData(char* pchDLCName, - unsigned int uiSortIndex, - char* pchImageURL) { - // on PS3 we get all the required info from the name - char chDLCType[3]; - int32_t hr = 0; - DLC_INFO* pDLCData = new DLC_INFO; - memset(pDLCData, 0, sizeof(DLC_INFO)); - - chDLCType[0] = pchDLCName[0]; - chDLCType[1] = pchDLCName[1]; - chDLCType[2] = 0; - - pDLCData->iConfig = app.GetiConfigFromName(pchDLCName); - pDLCData->uiSortIndex = uiSortIndex; - pDLCData->eDLCType = app.GetDLCTypeFromName(pchDLCName); - strcpy(pDLCData->chImageURL, pchImageURL); - // bool bIsTrialDLC = app.GetTrialFromName(pchDLCName); - - switch (pDLCData->eDLCType) { - case e_DLC_TexturePacks: { - char* pchName = (char*)malloc(strlen(pchDLCName) + 1); - strcpy(pchName, pchDLCName); - DLCTextures_PackID[pDLCData->iConfig] = pchName; - } break; - case e_DLC_MashupPacks: { - char* pchName = (char*)malloc(strlen(pchDLCName) + 1); - strcpy(pchName, pchDLCName); - DLCTextures_PackID[pDLCData->iConfig] = pchName; - } break; - default: - break; - } - - app.DebugPrintf(5, "Adding DLC - %s\n", pchDLCName); - DLCInfo[pchDLCName] = pDLCData; - - // if(ullOfferID_Trial!=0ll) DLCInfo_Trial[ullOfferID_Trial]=pDLCData; - // if(ullOfferID_Full!=0ll) DLCInfo_Full[ullOfferID_Full]=pDLCData; - // if(pFirstSkin[0]!=0) DLCInfo_SkinName[pFirstSkin]=ullOfferID_Full; - - // DLCInfo[ullOfferID_Trial]=pDLCData; - - return hr; -} #endif -bool Game::GetDLCFullOfferIDForSkinID(const std::wstring& FirstSkin, - uint64_t* pullVal) { - auto it = DLCInfo_SkinName.find(FirstSkin); - if (it == DLCInfo_SkinName.end()) { - return false; - } else { - *pullVal = (uint64_t)it->second; - return true; - } -} -bool Game::GetDLCFullOfferIDForPackID(const int iPackID, - uint64_t* pullVal) { - auto it = DLCTextures_PackID.find(iPackID); - if (it == DLCTextures_PackID.end()) { - *pullVal = (uint64_t)0; - return false; - } else { - *pullVal = (uint64_t)it->second; - return true; - } -} -DLC_INFO* Game::GetDLCInfoForTrialOfferID(uint64_t ullOfferID_Trial) { - // DLC_INFO *pDLCInfo=NULL; - if (DLCInfo_Trial.size() > 0) { - auto it = DLCInfo_Trial.find(ullOfferID_Trial); - if (it == DLCInfo_Trial.end()) { - // nothing for this - return nullptr; - } else { - return it->second; - } - } else - return nullptr; -} -DLC_INFO* Game::GetDLCInfoTrialOffer(int iIndex) { - std::unordered_map::iterator it = - DLCInfo_Trial.begin(); - for (int i = 0; i < iIndex; i++) { - ++it; - } - return it->second; -} -DLC_INFO* Game::GetDLCInfoFullOffer(int iIndex) { - std::unordered_map::iterator it = DLCInfo_Full.begin(); - for (int i = 0; i < iIndex; i++) { - ++it; - } - return it->second; -} -uint64_t Game::GetDLCInfoTexturesFullOffer(int iIndex) { - std::unordered_map::iterator it = DLCTextures_PackID.begin(); - for (int i = 0; i < iIndex; i++) { - ++it; - } - return it->second; -} -DLC_INFO* Game::GetDLCInfoForFullOfferID(uint64_t ullOfferID_Full) { - if (DLCInfo_Full.size() > 0) { - auto it = DLCInfo_Full.find(ullOfferID_Full); - if (it == DLCInfo_Full.end()) { - // nothing for this - return nullptr; - } else { - return it->second; - } - } else - return nullptr; -} -int Game::RemoteSaveThreadProc(void* lpParameter) { - // The game should be stopped while we are doing this, but the connections - // ticks may try to create some AABB's or Vec3's - Compression::UseDefaultThreadStorage(); - // 4J-PB - Xbox 360 - 163153 - [CRASH] TU17: Code: Multiplayer: During the - // Autosave in an online Multiplayer session, the game occasionally crashes - // for one or more Clients callstack - > if(tls->tileId != this->id) - // updateDefaultShape(); callstack - > - // default.exe!WaterlilyTile::getAABB(Level * level, int x, int y, int z) - // line 38 + 8 bytes C++ - // ... - // default.exe!Game::RemoteSaveThreadProc(void * - // lpParameter) line 6694 C++ - // host autosave, and the clients can crash on receiving handleMoveEntity - // when it's a tile within this thread, so need to do the tls for tiles - Tile::CreateNewThreadStorage(); - Minecraft* pMinecraft = Minecraft::GetInstance(); - pMinecraft->progressRenderer->progressStartNoAbort( - IDS_PROGRESS_HOST_SAVING); - pMinecraft->progressRenderer->progressStage(-1); - pMinecraft->progressRenderer->progressStagePercentage(0); - while (!app.GetGameStarted() && - app.GetXuiAction(ProfileManager.GetPrimaryPad()) == - eAppAction_WaitRemoteServerSaveComplete) { - // Tick all the games connections - pMinecraft->tickAllConnections(); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } - - if (app.GetXuiAction(ProfileManager.GetPrimaryPad()) != - eAppAction_WaitRemoteServerSaveComplete) { - // Something cancelled us? - return ERROR_CANCELLED; - } - app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_Idle); - - ui.UpdatePlayerBasePositions(); - - Tile::ReleaseThreadStorage(); - - return 0; -} - -void Game::ExitGameFromRemoteSave(void* lpParameter) { - int primaryPad = ProfileManager.GetPrimaryPad(); - - unsigned int uiIDA[3]; - uiIDA[0] = IDS_CONFIRM_CANCEL; - uiIDA[1] = IDS_CONFIRM_OK; - - ui.RequestAlertMessage( - IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 2, primaryPad, - &Game::ExitGameFromRemoteSaveDialogReturned, nullptr); -} - -int Game::ExitGameFromRemoteSaveDialogReturned( - void* pParam, int iPad, C4JStorage::EMessageResult result) { - // CScene_Pause* pClass = (CScene_Pause*)pParam; - - // results switched for this dialog - if (result == C4JStorage::EMessage_ResultDecline) { - app.SetAction(iPad, eAppAction_ExitWorld); - } else { - // Inform fullscreen progress scene that it's not being cancelled after - // all - UIScene_FullscreenProgress* pScene = - (UIScene_FullscreenProgress*)ui.FindScene( - eUIScene_FullscreenProgress); - if (pScene != nullptr) { - pScene->SetWasCancelled(false); - } - } - return 0; -} - -unsigned int Game::AddDLCRequest(eDLCMarketplaceType eType, - bool bPromote) { - // lock access - { - std::lock_guard lock(csDLCDownloadQueue); - - // If it's already in there, promote it to the top of the list - int iPosition = 0; - for (auto it = m_DLCDownloadQueue.begin(); - it != m_DLCDownloadQueue.end(); ++it) { - DLCRequest* pCurrent = *it; - - if (pCurrent->dwType == m_dwContentTypeA[eType]) { - // already got this in the list - if (pCurrent->eState == e_DLC_ContentState_Retrieving || - pCurrent->eState == e_DLC_ContentState_Retrieved) { - // already retrieved this - return 0; - } else { - // promote - if (bPromote) { - m_DLCDownloadQueue.erase(m_DLCDownloadQueue.begin() + - iPosition); - m_DLCDownloadQueue.insert(m_DLCDownloadQueue.begin(), - pCurrent); - } - return 0; - } - } - iPosition++; - } - - DLCRequest* pDLCreq = new DLCRequest; - pDLCreq->dwType = m_dwContentTypeA[eType]; - pDLCreq->eState = e_DLC_ContentState_Idle; - - m_DLCDownloadQueue.push_back(pDLCreq); - - m_bAllDLCContentRetrieved = false; - } - - app.DebugPrintf("[Consoles_App] Added DLC request.\n"); - return 1; -} - -unsigned int Game::AddTMSPPFileTypeRequest(eDLCContentType eType, - bool bPromote) { - // lock access - std::lock_guard lock(csTMSPPDownloadQueue); - - // If it's already in there, promote it to the top of the list - int iPosition = 0; - // ignore promoting for now - /* - bool bPromoted=false; - - - for(auto it = m_TMSPPDownloadQueue.begin(); it != - m_TMSPPDownloadQueue.end(); ++it) - { - TMSPPRequest *pCurrent = *it; - - if(pCurrent->eType==eType) - { - if(!(pCurrent->eState == e_TMS_ContentState_Retrieving || pCurrent->eState - == e_TMS_ContentState_Retrieved)) - { - // promote - if(bPromote) - { - m_TMSPPDownloadQueue.erase(m_TMSPPDownloadQueue.begin()+iPosition); - m_TMSPPDownloadQueue.insert(m_TMSPPDownloadQueue.begin(),pCurrent); - bPromoted=true; - } - } - } - iPosition++; - } - - if(bPromoted) - { - // re-ordered the list, so leave now - return 0; - } - */ - - // special case for data files (not image files) - if (eType == e_DLC_TexturePackData) { - int iCount = GetDLCInfoFullOffersCount(); - - for (int i = 0; i < iCount; i++) { - DLC_INFO* pDLC = GetDLCInfoFullOffer(i); - - if ((pDLC->eDLCType == e_DLC_TexturePacks) || - (pDLC->eDLCType == e_DLC_MashupPacks)) { - // first check if the image is already in the memory textures, - // since we might be loading some from the Title Update - // partition - if (pDLC->wchDataFile[0] != 0) { - // wchar_t *cString = pDLC->wchDataFile; - // 4J-PB - shouldn't check this here - let the TMS files - // override it, so if they are on TMS, we'll take them - // first - // int iIndex = - // app.GetLocalTMSFileIndex(pDLC->wchDataFile,true); - - // if(iIndex!=-1) - { - bool bPresent = app.IsFileInTPD(pDLC->iConfig); - - if (!bPresent) { - // this may already be present in the vector because - // of a previous trial/full offer - - bool bAlreadyInQueue = false; - for (auto it = m_TMSPPDownloadQueue.begin(); - it != m_TMSPPDownloadQueue.end(); ++it) { - TMSPPRequest* pCurrent = *it; - - if (wcscmp(pDLC->wchDataFile, - pCurrent->wchFilename) == 0) { - bAlreadyInQueue = true; - break; - } - } - - if (!bAlreadyInQueue) { - TMSPPRequest* pTMSPPreq = new TMSPPRequest; - - pTMSPPreq->CallbackFunc = - &Game::TMSPPFileReturned; - pTMSPPreq->lpCallbackParam = this; - pTMSPPreq->eStorageFacility = - C4JStorage::eGlobalStorage_Title; - pTMSPPreq->eFileTypeVal = - C4JStorage::TMS_FILETYPE_BINARY; - memcpy(pTMSPPreq->wchFilename, - pDLC->wchDataFile, - sizeof(wchar_t) * MAX_BANNERNAME_SIZE); - pTMSPPreq->eType = e_DLC_TexturePackData; - pTMSPPreq->eState = e_TMS_ContentState_Queued; - m_bAllTMSContentRetrieved = false; - m_TMSPPDownloadQueue.push_back(pTMSPPreq); - } - } else { - app.DebugPrintf( - "Texture data already present in the TPD\n"); - } - } - } - } - } - } else { // for all the files of type eType, add them to the download list - - // run through the trial offers first, then the full offers. Any - // duplicates won't be added to the download queue - int iCount; - // and the full offers - - iCount = GetDLCInfoFullOffersCount(); - for (int i = 0; i < iCount; i++) { - DLC_INFO* pDLC = GetDLCInfoFullOffer(i); - // if(wcscmp(pDLC->wchType,wchDLCTypeNames[eType])==0) - if (pDLC->eDLCType == eType) { - // first check if the image is already in the memory textures, - // since we might be loading some from the Title Update - // partition - - wchar_t* cString = pDLC->wchBanner; - // 4J-PB - shouldn't check this here - let the TMS files - // override it, so if they are on TMS, we'll take them first - // int iIndex = app.GetLocalTMSFileIndex(cString,true); - - // if(iIndex!=-1) - { - bool bPresent = app.IsFileInMemoryTextures(cString); - - if (!bPresent) { - // this may already be present in the vector because of - // a previous trial/full offer - - bool bAlreadyInQueue = false; - for (auto it = m_TMSPPDownloadQueue.begin(); - it != m_TMSPPDownloadQueue.end(); ++it) { - TMSPPRequest* pCurrent = *it; - - if (wcscmp(pDLC->wchBanner, - pCurrent->wchFilename) == 0) { - bAlreadyInQueue = true; - break; - } - } - - if (!bAlreadyInQueue) { - // app.DebugPrintf("Adding a request to the TMSPP - // download queue - %ls\n",pDLC->wchBanner); - TMSPPRequest* pTMSPPreq = new TMSPPRequest; - memset(pTMSPPreq, 0, sizeof(TMSPPRequest)); - - pTMSPPreq->CallbackFunc = - &Game::TMSPPFileReturned; - pTMSPPreq->lpCallbackParam = this; - // 4J-PB - testing for now - // pTMSPPreq->eStorageFacility=C4JStorage::eGlobalStorage_TitleUser; - pTMSPPreq->eStorageFacility = - C4JStorage::eGlobalStorage_Title; - pTMSPPreq->eFileTypeVal = - C4JStorage::TMS_FILETYPE_BINARY; - // wcstombs(pTMSPPreq->szFilename,pDLC->wchBanner,MAX_TMSFILENAME_SIZE); - - memcpy(pTMSPPreq->wchFilename, pDLC->wchBanner, - sizeof(wchar_t) * MAX_BANNERNAME_SIZE); - pTMSPPreq->eType = eType; - pTMSPPreq->eState = e_TMS_ContentState_Queued; - m_bAllTMSContentRetrieved = false; - m_TMSPPDownloadQueue.push_back(pTMSPPreq); - app.DebugPrintf( - "===m_TMSPPDownloadQueue Adding %ls, q size is " - "%d\n", - pTMSPPreq->wchFilename, - m_TMSPPDownloadQueue.size()); - } - } - } - } - } - } - - return 1; -} - -bool Game::CheckTMSDLCCanStop() { - std::lock_guard lock(csTMSPPDownloadQueue); - for (auto it = m_TMSPPDownloadQueue.begin(); - it != m_TMSPPDownloadQueue.end(); ++it) { - TMSPPRequest* pCurrent = *it; - - if (pCurrent->eState == e_TMS_ContentState_Retrieving) { - return false; - } - } - - return true; -} - -bool Game::RetrieveNextDLCContent() { - // If there's already a retrieve in progress, quit - // we may have re-ordered the list, so need to check every item - - // is there a primary player and a network connection? - int primPad = ProfileManager.GetPrimaryPad(); - if (primPad == -1 || !ProfileManager.IsSignedInLive(primPad)) { - return true; // 4J-JEV: We need to wait until the primary player is - // online. - } - - { - std::lock_guard lock(csDLCDownloadQueue); - for (auto it = m_DLCDownloadQueue.begin(); - it != m_DLCDownloadQueue.end(); ++it) { - DLCRequest* pCurrent = *it; - - if (pCurrent->eState == e_DLC_ContentState_Retrieving) { - return true; - } - } - - // Now look for the next retrieval - for (auto it = m_DLCDownloadQueue.begin(); - it != m_DLCDownloadQueue.end(); ++it) { - DLCRequest* pCurrent = *it; - - if (pCurrent->eState == e_DLC_ContentState_Idle) { -#if defined(_DEBUG) - app.DebugPrintf("RetrieveNextDLCContent - type = %d\n", - pCurrent->dwType); -#endif - - C4JStorage::EDLCStatus status = StorageManager.GetDLCOffers( - ProfileManager.GetPrimaryPad(), - [this](int iOfferC, std::uint32_t dwType, int pad) { - return dlcOffersReturned(iOfferC, dwType, pad); - }, - pCurrent->dwType); - if (status == C4JStorage::EDLC_Pending) { - pCurrent->eState = e_DLC_ContentState_Retrieving; - } else { - // no content of this type, or some other problem - app.DebugPrintf("RetrieveNextDLCContent - PROBLEM\n"); - pCurrent->eState = e_DLC_ContentState_Retrieved; - } - return true; - } - } - } - - app.DebugPrintf("[Consoles_App] Finished downloading dlc content.\n"); - return false; -} - -int Game::TMSPPFileReturned(void* pParam, int iPad, int iUserData, - C4JStorage::PTMSPP_FILEDATA pFileData, - const char* szFilename) { - Game* pClass = (Game*)pParam; - - // find the right one in the vector - { - std::lock_guard lock(pClass->csTMSPPDownloadQueue); - for (auto it = pClass->m_TMSPPDownloadQueue.begin(); - it != pClass->m_TMSPPDownloadQueue.end(); ++it) { - TMSPPRequest* pCurrent = *it; -#if defined(_WINDOWS64) - char szFile[MAX_TMSFILENAME_SIZE]; - wcstombs(szFile, pCurrent->wchFilename, MAX_TMSFILENAME_SIZE); - - if (strcmp(szFilename, szFile) == 0) -#endif - { - // set this to retrieved whether it found it or not - pCurrent->eState = e_TMS_ContentState_Retrieved; - - if (pFileData != nullptr) { - switch (pCurrent->eType) { - case e_DLC_TexturePackData: { - app.DebugPrintf("--- Got texturepack data %ls\n", - pCurrent->wchFilename); - // get the config value for the texture pack - int iConfig = - app.GetTPConfigVal(pCurrent->wchFilename); - app.AddMemoryTPDFile(iConfig, pFileData->pbData, - pFileData->size); - } break; - default: - app.DebugPrintf("--- Got image data - %ls\n", - pCurrent->wchFilename); - app.AddMemoryTextureFile(pCurrent->wchFilename, - pFileData->pbData, - pFileData->size); - break; - } - } else { - app.DebugPrintf("TMSImageReturned failed (%s)...\n", - szFilename); - } - break; - } - } - } - - return 0; -} - -bool Game::RetrieveNextTMSPPContent() { return false; } - -void Game::TickDLCOffersRetrieved() { - if (!m_bAllDLCContentRetrieved) { - if (!app.RetrieveNextDLCContent()) { - app.DebugPrintf("[Consoles_App] All content retrieved.\n"); - m_bAllDLCContentRetrieved = true; - } - } -} -void Game::ClearAndResetDLCDownloadQueue() { - app.DebugPrintf("[Consoles_App] Clear and reset download queue.\n"); - - int iPosition = 0; - { - std::lock_guard lock(csTMSPPDownloadQueue); - for (auto it = m_DLCDownloadQueue.begin(); - it != m_DLCDownloadQueue.end(); ++it) { - DLCRequest* pCurrent = *it; - - delete pCurrent; - iPosition++; - } - m_DLCDownloadQueue.clear(); - m_bAllDLCContentRetrieved = true; - } -} - -void Game::TickTMSPPFilesRetrieved() { - if (m_bTickTMSDLCFiles && !m_bAllTMSContentRetrieved) { - if (app.RetrieveNextTMSPPContent() == false) { - m_bAllTMSContentRetrieved = true; - } - } -} -void Game::ClearTMSPPFilesRetrieved() { - int iPosition = 0; - { - std::lock_guard lock(csTMSPPDownloadQueue); - for (auto it = m_TMSPPDownloadQueue.begin(); - it != m_TMSPPDownloadQueue.end(); ++it) { - TMSPPRequest* pCurrent = *it; - - delete pCurrent; - iPosition++; - } - m_TMSPPDownloadQueue.clear(); - m_bAllTMSContentRetrieved = true; - } -} - -int Game::dlcOffersReturned(int iOfferC, std::uint32_t dwType, - int iPad) { - // find the right one in the vector - { - std::lock_guard lock(csTMSPPDownloadQueue); - for (auto it = m_DLCDownloadQueue.begin(); - it != m_DLCDownloadQueue.end(); ++it) { - DLCRequest* pCurrent = *it; - - // avatar items are coming back as type Content, so we can't trust - // the type setting - if (pCurrent->dwType == static_cast(dwType)) { - m_iDLCOfferC = iOfferC; - DebugPrintf( - "DLCOffersReturned - type %u, count %d - setting to " - "retrieved\n", - dwType, iOfferC); - pCurrent->eState = e_DLC_ContentState_Retrieved; - break; - } - } - } - return 0; -} - -eDLCContentType Game::Find_eDLCContentType(std::uint32_t dwType) { - for (int i = 0; i < e_DLC_MAX; i++) { - if (m_dwContentTypeA[i] == dwType) { - return (eDLCContentType)i; - } - } - return (eDLCContentType)0; -} -bool Game::DLCContentRetrieved(eDLCMarketplaceType eType) { - // If there's already a retrieve in progress, quit - // we may have re-ordered the list, so need to check every item - std::lock_guard lock(csDLCDownloadQueue); - for (auto it = m_DLCDownloadQueue.begin(); it != m_DLCDownloadQueue.end(); - ++it) { - DLCRequest* pCurrent = *it; - - if ((pCurrent->dwType == m_dwContentTypeA[eType]) && - (pCurrent->eState == e_DLC_ContentState_Retrieved)) { - return true; - } - } - return false; -} // DLC -int Game::GetDLCInfoTrialOffersCount() { - return (int)DLCInfo_Trial.size(); -} -int Game::GetDLCInfoFullOffersCount() { - return (int)DLCInfo_Full.size(); -} -int Game::GetDLCInfoTexturesOffersCount() { - return (int)DLCTextures_PackID.size(); -} // AUTOSAVE void Game::SetAutosaveTimerTime(void) { @@ -5903,12 +2091,6 @@ bool Game::IsLocalMultiplayerAvailable() { // 4J-PB - language and locale function // (moved to manager class) -void Game::SetTickTMSDLCFiles(bool bVal) { - // 4J-PB - we need to stop the retrieval of minecraft store images from TMS - // when we aren't in the DLC, since going in to Play Game will change the - // title id group - m_bTickTMSDLCFiles = bVal; -} std::wstring Game::getFilePath(std::uint32_t packId, std::wstring filename, diff --git a/targets/app/common/Game.h b/targets/app/common/Game.h index 3e297c1b3..dfcc83fb3 100644 --- a/targets/app/common/Game.h +++ b/targets/app/common/Game.h @@ -12,9 +12,13 @@ #include "app/common/ArchiveManager.h" #include "app/common/BannedListManager.h" #include "app/common/DebugOptions.h" +#include "app/common/DLCController.h" +#include "app/common/GameSettingsManager.h" #include "app/common/IPlatformGame.h" #include "app/common/App_structs.h" #include "app/common/LocalizationManager.h" +#include "app/common/MenuController.h" +#include "app/common/NetworkController.h" #include "app/common/SaveManager.h" #include "app/common/SkinManager.h" #include "app/common/TerrainFeatureManager.h" @@ -32,11 +36,7 @@ #include "minecraft/network/packet/DisconnectPacket.h" #include "minecraft/world/entity/item/MinecartHopper.h" -typedef struct _JoinFromInviteData { - std::uint32_t dwUserIndex; // dwUserIndex - std::uint32_t dwLocalUsersMask; // dwUserMask - const INVITE_INFO* pInviteInfo; // pInviteInfo -} JoinFromInviteData; +// JoinFromInviteData moved to NetworkController.h class Player; class Inventory; @@ -82,10 +82,13 @@ public: LocalizationManager m_localizationManager; ArchiveManager m_archiveManager; SkinManager m_skinManager; + GameSettingsManager m_gameSettingsManager; + DLCController m_dlcController; + NetworkController m_networkController; + MenuController m_menuController; - // storing credits text from the DLC - std::vector m_vCreditText; // hold the credit text lines so - // we can avoid duplicating them + // storing credits text from the DLC - delegated to DLCController + std::vector& m_vCreditText = m_dlcController.m_vCreditText; // In builds prior to TU5, the size of the GAME_SETTINGS struct was 204 // bytes. We added a few new values to the internal struct in TU5, and even @@ -128,7 +131,7 @@ public: static const int USER_UI = 7; // 4J Stu - This also makes it appear on the UI console - void HandleButtonPresses(); + void HandleButtonPresses() { m_gameSettingsManager.handleButtonPresses(); } bool IntroRunning() { return m_bIntroRunning; } void SetIntroRunning(bool bSet) { m_bIntroRunning = bSet; } #if defined(_CONTENT_PACKAGE) @@ -142,7 +145,9 @@ public: bool IsAppPaused(); void SetAppPaused(bool val); - int displaySavingMessage(const C4JStorage::ESavingMessage eMsg, int iPad); + int displaySavingMessage(const C4JStorage::ESavingMessage eMsg, int iPad) { + return m_gameSettingsManager.displaySavingMessage(eMsg, iPad); + } bool GetGameStarted() { return m_bGameStarted; } void SetGameStarted(bool bVal) { if (bVal) @@ -154,51 +159,87 @@ public: } int GetLocalPlayerCount(void); bool LoadInventoryMenu(int iPad, std::shared_ptr player, - bool bNavigateBack = false); + bool bNavigateBack = false) { + return m_menuController.loadInventoryMenu(iPad, player, bNavigateBack); + } bool LoadCreativeMenu(int iPad, std::shared_ptr player, - bool bNavigateBack = false); + bool bNavigateBack = false) { + return m_menuController.loadCreativeMenu(iPad, player, bNavigateBack); + } bool LoadEnchantingMenu(int iPad, std::shared_ptr inventory, int x, int y, int z, Level* level, - const std::wstring& name); + const std::wstring& name) { + return m_menuController.loadEnchantingMenu(iPad, inventory, x, y, z, level, name); + } bool LoadFurnaceMenu(int iPad, std::shared_ptr inventory, - std::shared_ptr furnace); + std::shared_ptr furnace) { + return m_menuController.loadFurnaceMenu(iPad, inventory, furnace); + } bool LoadBrewingStandMenu( int iPad, std::shared_ptr inventory, - std::shared_ptr brewingStand); + std::shared_ptr brewingStand) { + return m_menuController.loadBrewingStandMenu(iPad, inventory, brewingStand); + } bool LoadContainerMenu(int iPad, std::shared_ptr inventory, - std::shared_ptr container); + std::shared_ptr container) { + return m_menuController.loadContainerMenu(iPad, inventory, container); + } bool LoadTrapMenu(int iPad, std::shared_ptr inventory, - std::shared_ptr trap); - bool LoadCrafting2x2Menu(int iPad, std::shared_ptr player); + std::shared_ptr trap) { + return m_menuController.loadTrapMenu(iPad, inventory, trap); + } + bool LoadCrafting2x2Menu(int iPad, std::shared_ptr player) { + return m_menuController.loadCrafting2x2Menu(iPad, player); + } bool LoadCrafting3x3Menu(int iPad, std::shared_ptr player, - int x, int y, int z); + int x, int y, int z) { + return m_menuController.loadCrafting3x3Menu(iPad, player, x, y, z); + } bool LoadFireworksMenu(int iPad, std::shared_ptr player, int x, - int y, int z); - bool LoadSignEntryMenu(int iPad, std::shared_ptr sign); + int y, int z) { + return m_menuController.loadFireworksMenu(iPad, player, x, y, z); + } + bool LoadSignEntryMenu(int iPad, std::shared_ptr sign) { + return m_menuController.loadSignEntryMenu(iPad, sign); + } bool LoadRepairingMenu(int iPad, std::shared_ptr inventory, - Level* level, int x, int y, int z); + Level* level, int x, int y, int z) { + return m_menuController.loadRepairingMenu(iPad, inventory, level, x, y, z); + } bool LoadTradingMenu(int iPad, std::shared_ptr inventory, std::shared_ptr trader, Level* level, - const std::wstring& name); + const std::wstring& name) { + return m_menuController.loadTradingMenu(iPad, inventory, trader, level, name); + } bool LoadCommandBlockMenu( int iPad, std::shared_ptr commandBlock) { return false; } bool LoadHopperMenu(int iPad, std::shared_ptr inventory, - std::shared_ptr hopper); + std::shared_ptr hopper) { + return m_menuController.loadHopperMenu(iPad, inventory, hopper); + } bool LoadHopperMenu(int iPad, std::shared_ptr inventory, - std::shared_ptr hopper); + std::shared_ptr hopper) { + return m_menuController.loadHopperMenu(iPad, inventory, hopper); + } bool LoadHorseMenu(int iPad, std::shared_ptr inventory, std::shared_ptr container, - std::shared_ptr horse); + std::shared_ptr horse) { + return m_menuController.loadHorseMenu(iPad, inventory, container, horse); + } bool LoadBeaconMenu(int iPad, std::shared_ptr inventory, - std::shared_ptr beacon); + std::shared_ptr beacon) { + return m_menuController.loadBeaconMenu(iPad, inventory, beacon); + } bool GetTutorialMode() { return m_bTutorialMode; } void SetTutorialMode(bool bSet) { m_bTutorialMode = bSet; } - void SetSpecialTutorialCompletionFlag(int iPad, int index); + void SetSpecialTutorialCompletionFlag(int iPad, int index) { + m_gameSettingsManager.setSpecialTutorialCompletionFlag(iPad, index); + } static const wchar_t* GetString(int iID); StringTable* getStringTable() const { return m_localizationManager.getStringTable(); } @@ -206,50 +247,53 @@ public: eGameMode GetGameMode() { return m_eGameMode; } void SetGameMode(eGameMode eMode) { m_eGameMode = eMode; } - eXuiAction GetGlobalXuiAction() { return m_eGlobalXuiAction; } - void SetGlobalXuiAction(eXuiAction action) { m_eGlobalXuiAction = action; } - eXuiAction GetXuiAction(int iPad) { return m_eXuiAction[iPad]; } - void SetAction(int iPad, eXuiAction action, void* param = nullptr); - void SetTMSAction(int iPad, eTMSAction action) { - m_eTMSAction[iPad] = action; + eXuiAction GetGlobalXuiAction() { return m_menuController.getGlobalXuiAction(); } + void SetGlobalXuiAction(eXuiAction action) { m_menuController.setGlobalXuiAction(action); } + eXuiAction GetXuiAction(int iPad) { return m_menuController.getXuiAction(iPad); } + void SetAction(int iPad, eXuiAction action, void* param = nullptr) { + m_menuController.setAction(iPad, action, param); } - eTMSAction GetTMSAction(int iPad) { return m_eTMSAction[iPad]; } + void SetTMSAction(int iPad, eTMSAction action) { + m_menuController.setTMSAction(iPad, action); + } + eTMSAction GetTMSAction(int iPad) { return m_menuController.getTMSAction(iPad); } eXuiServerAction GetXuiServerAction(int iPad) { - return m_eXuiServerAction[iPad]; + return m_menuController.getXuiServerAction(iPad); } void* GetXuiServerActionParam(int iPad) { - return m_eXuiServerActionParam[iPad]; + return m_menuController.getXuiServerActionParam(iPad); } void SetXuiServerAction(int iPad, eXuiServerAction action, void* param = nullptr) { - m_eXuiServerAction[iPad] = action; - m_eXuiServerActionParam[iPad] = param; + m_menuController.setXuiServerAction(iPad, action, param); } eXuiServerAction GetGlobalXuiServerAction() { - return m_eGlobalXuiServerAction; + return m_menuController.getGlobalXuiServerAction(); } void SetGlobalXuiServerAction(eXuiServerAction action) { - m_eGlobalXuiServerAction = action; + m_menuController.setGlobalXuiServerAction(action); } DisconnectPacket::eDisconnectReason GetDisconnectReason() { - return m_disconnectReason; + return m_networkController.getDisconnectReason(); } void SetDisconnectReason(DisconnectPacket::eDisconnectReason bVal) { - m_disconnectReason = bVal; + m_networkController.setDisconnectReason(bVal); } - bool GetChangingSessionType() { return m_bChangingSessionType; } - void SetChangingSessionType(bool bVal) { m_bChangingSessionType = bVal; } + bool GetChangingSessionType() { return m_networkController.getChangingSessionType(); } + void SetChangingSessionType(bool bVal) { m_networkController.setChangingSessionType(bVal); } - bool GetReallyChangingSessionType() { return m_bReallyChangingSessionType; } + bool GetReallyChangingSessionType() { return m_networkController.getReallyChangingSessionType(); } void SetReallyChangingSessionType(bool bVal) { - m_bReallyChangingSessionType = bVal; + m_networkController.setReallyChangingSessionType(bVal); } // 4J Stu - Added so that we can call this when a confirmation box is // selected - static void SetActionConfirmed(void* param); + static void SetActionConfirmed(void* param) { + GameSettingsManager::setActionConfirmed(param); + } void HandleXuiActions(void); // 4J Stu - Functions used for Minecon and other promo work @@ -292,21 +336,33 @@ public: // void GetPreviewImage(int iPad,XSOCIAL_PREVIEWIMAGE // *preview); - void InitGameSettings(); + void InitGameSettings() { m_gameSettingsManager.initGameSettings(); } static int OldProfileVersionCallback(void* pParam, unsigned char* pucData, const unsigned short usVersion, - const int iPad); + const int iPad) { + return GameSettingsManager::oldProfileVersionCallback(pParam, pucData, usVersion, iPad); + } static int DefaultOptionsCallback(void* pParam, C_4JProfile::PROFILESETTINGS* pSettings, - const int iPad); + const int iPad) { + return GameSettingsManager::defaultOptionsCallback(pParam, pSettings, iPad); + } int SetDefaultOptions(C_4JProfile::PROFILESETTINGS* pSettings, - const int iPad); + const int iPad) { + return m_gameSettingsManager.setDefaultOptions(pSettings, iPad); + } void SetRichPresenceContext(int iPad, int contextId) override = 0; - void SetGameSettings(int iPad, eGameSetting eVal, unsigned char ucVal); - unsigned char GetGameSettings(int iPad, eGameSetting eVal); - unsigned char GetGameSettings(eGameSetting eVal); // for the primary pad + void SetGameSettings(int iPad, eGameSetting eVal, unsigned char ucVal) { + m_gameSettingsManager.setGameSettings(iPad, eVal, ucVal); + } + unsigned char GetGameSettings(int iPad, eGameSetting eVal) { + return m_gameSettingsManager.getGameSettings(iPad, eVal); + } + unsigned char GetGameSettings(eGameSetting eVal) { + return m_gameSettingsManager.getGameSettings(eVal); + } void SetPlayerSkin(int iPad, const std::wstring& name) { m_skinManager.setPlayerSkin(iPad, name, GameSettingsA); } @@ -338,28 +394,41 @@ public: m_skinManager.validateFavoriteSkins(iPad, GameSettingsA, m_dlcManager); } - // Mash-up pack worlds hide/display - void HideMashupPackWorld(int iPad, unsigned int iMashupPackID); - void EnableMashupPackWorlds(int iPad); - unsigned int GetMashupPackWorlds(int iPad); + // Mash-up pack worlds hide/display - delegated to GameSettingsManager + void HideMashupPackWorld(int iPad, unsigned int iMashupPackID) { + m_gameSettingsManager.hideMashupPackWorld(iPad, iMashupPackID); + } + void EnableMashupPackWorlds(int iPad) { + m_gameSettingsManager.enableMashupPackWorlds(iPad); + } + unsigned int GetMashupPackWorlds(int iPad) { + return m_gameSettingsManager.getMashupPackWorlds(iPad); + } - // Minecraft language select - implementations remain in Game.cpp - // (they access GameSettingsA directly) - void SetMinecraftLanguage(int iPad, unsigned char ucLanguage); - unsigned char GetMinecraftLanguage(int iPad); - void SetMinecraftLocale(int iPad, unsigned char ucLanguage); - unsigned char GetMinecraftLocale(int iPad); + // Minecraft language select - delegated to GameSettingsManager + void SetMinecraftLanguage(int iPad, unsigned char ucLanguage) { + m_gameSettingsManager.setMinecraftLanguage(iPad, ucLanguage); + } + unsigned char GetMinecraftLanguage(int iPad) { + return m_gameSettingsManager.getMinecraftLanguage(iPad); + } + void SetMinecraftLocale(int iPad, unsigned char ucLanguage) { + m_gameSettingsManager.setMinecraftLocale(iPad, ucLanguage); + } + unsigned char GetMinecraftLocale(int iPad) { + return m_gameSettingsManager.getMinecraftLocale(iPad); + } // 4J-PB - set a timer when the user navigates the quickselect, so we can // bring the opacity back to defaults for a short time unsigned int GetOpacityTimer(int iPad) { - return m_uiOpacityCountDown[iPad]; + return m_menuController.getOpacityTimer(iPad); } void SetOpacityTimer(int iPad) { - m_uiOpacityCountDown[iPad] = 120; + m_menuController.setOpacityTimer(iPad); } // 6 seconds void TickOpacityTimer(int iPad) { - if (m_uiOpacityCountDown[iPad] > 0) m_uiOpacityCountDown[iPad]--; + m_menuController.tickOpacityTimer(iPad); } public: @@ -379,28 +448,54 @@ public: return m_skinManager.getAdditionalModelParts(iPad); } void CheckGameSettingsChanged(bool bOverride5MinuteTimer = false, - int iPad = XUSER_INDEX_ANY); - void ApplyGameSettingsChanged(int iPad); - void ClearGameSettingsChangedFlag(int iPad); - void ActionGameSettings(int iPad, eGameSetting eVal); + int iPad = XUSER_INDEX_ANY) { + m_gameSettingsManager.checkGameSettingsChanged(bOverride5MinuteTimer, iPad); + } + void ApplyGameSettingsChanged(int iPad) { + m_gameSettingsManager.applyGameSettingsChanged(iPad); + } + void ClearGameSettingsChangedFlag(int iPad) { + m_gameSettingsManager.clearGameSettingsChangedFlag(iPad); + } + void ActionGameSettings(int iPad, eGameSetting eVal) { + m_gameSettingsManager.actionGameSettings(iPad, eVal); + } unsigned int GetGameSettingsDebugMask(int iPad = -1, - bool bOverridePlayer = false); - void SetGameSettingsDebugMask(int iPad, unsigned int uiVal); - void ActionDebugMask(int iPad, bool bSetAllClear = false); + bool bOverridePlayer = false) { + return m_gameSettingsManager.getGameSettingsDebugMask(iPad, bOverridePlayer); + } + void SetGameSettingsDebugMask(int iPad, unsigned int uiVal) { + m_gameSettingsManager.setGameSettingsDebugMask(iPad, uiVal); + } + void ActionDebugMask(int iPad, bool bSetAllClear = false) { + m_gameSettingsManager.actionDebugMask(iPad, bSetAllClear); + } // bool IsLocalMultiplayerAvailable(); - // for sign in change monitoring + // for sign in change monitoring - delegated to NetworkController static void SignInChangeCallback(void* pParam, bool bVal, - unsigned int uiSignInData); - static void ClearSignInChangeUsersMask(); - static int SignoutExitWorldThreadProc(void* lpParameter); + unsigned int uiSignInData) { + NetworkController::signInChangeCallback(pParam, bVal, uiSignInData); + } + static void ClearSignInChangeUsersMask() { + NetworkController::clearSignInChangeUsersMask(); + } + static int SignoutExitWorldThreadProc(void* lpParameter) { + return NetworkController::signoutExitWorldThreadProc(lpParameter); + } static int PrimaryPlayerSignedOutReturned(void* pParam, int iPad, - const C4JStorage::EMessageResult); + const C4JStorage::EMessageResult result) { + return NetworkController::primaryPlayerSignedOutReturned(pParam, iPad, result); + } static int EthernetDisconnectReturned(void* pParam, int iPad, - const C4JStorage::EMessageResult); - static void ProfileReadErrorCallback(void* pParam); + const C4JStorage::EMessageResult result) { + return NetworkController::ethernetDisconnectReturned(pParam, iPad, result); + } + static void ProfileReadErrorCallback(void* pParam) { + NetworkController::profileReadErrorCallback(pParam); + } // FATAL LOAD ERRORS virtual void FatalLoadError(); @@ -408,12 +503,16 @@ public: // Notifications from the game listener to be passed to the qnet listener static void NotificationsCallback(void* pParam, std::uint32_t dwNotification, - unsigned int uiParam); + unsigned int uiParam) { + NetworkController::notificationsCallback(pParam, dwNotification, uiParam); + } // for the ethernet being disconnected - static void LiveLinkChangeCallback(void* pParam, bool bConnected); - bool GetLiveLinkRequired() { return m_bLiveLinkRequired; } - void SetLiveLinkRequired(bool required) { m_bLiveLinkRequired = required; } + static void LiveLinkChangeCallback(void* pParam, bool bConnected) { + NetworkController::liveLinkChangeCallback(pParam, bConnected); + } + bool GetLiveLinkRequired() { return m_networkController.getLiveLinkRequired(); } + void SetLiveLinkRequired(bool required) { m_networkController.setLiveLinkRequired(required); } #if defined(_DEBUG_MENUS_ENABLED) bool DebugSettingsOn() { return m_debugOptions.settingsOn(); } @@ -426,39 +525,34 @@ public: // bool UploadFileToGlobalStorage(int iQuadrant, // C4JStorage::eGlobalStorage eStorageFacility, std::wstring *wsFile ); - // Installed DLC - bool StartInstallDLCProcess(int iPad); - int dlcInstalledCallback(int iOfferC, int iPad); + // Installed DLC - delegated to DLCController + bool StartInstallDLCProcess(int iPad) { return m_dlcController.startInstallDLCProcess(iPad); } + int dlcInstalledCallback(int iOfferC, int iPad) { return m_dlcController.dlcInstalledCallback(iOfferC, iPad); } void HandleDLCLicenseChange(); int dlcMountedCallback(int iPad, std::uint32_t dwErr, - std::uint32_t dwLicenceMask); - void MountNextDLC(int iPad); - // static int DLCReadCallback(void* pParam,C4JStorage::DLC_FILE_DETAILS - // *pDLCData); - void HandleDLC(DLCPack* pack); - bool DLCInstallPending() { return m_bDLCInstallPending; } - bool DLCInstallProcessCompleted() { return m_bDLCInstallProcessCompleted; } - void ClearDLCInstalled() { m_bDLCInstallProcessCompleted = false; } + std::uint32_t dwLicenceMask) { + return m_dlcController.dlcMountedCallback(iPad, dwErr, dwLicenceMask); + } + void MountNextDLC(int iPad) { m_dlcController.mountNextDLC(iPad); } + void HandleDLC(DLCPack* pack) { m_dlcController.handleDLC(pack); } + bool DLCInstallPending() { return m_dlcController.dlcInstallPending(); } + bool DLCInstallProcessCompleted() { return m_dlcController.dlcInstallProcessCompleted(); } + void ClearDLCInstalled() { m_dlcController.clearDLCInstalled(); } static int MarketplaceCountsCallback(void* pParam, - C4JStorage::DLC_TMS_DETAILS*, - int iPad); - - bool AlreadySeenCreditText(const std::wstring& wstemp); - - void ClearNewDLCAvailable(void) { - m_bNewDLCAvailable = false; - m_bSeenNewDLCTip = true; + C4JStorage::DLC_TMS_DETAILS* details, + int iPad) { + return DLCController::marketplaceCountsCallback(pParam, details, iPad); } - bool GetNewDLCAvailable() { return m_bNewDLCAvailable; } - void DisplayNewDLCTipAgain() { m_bSeenNewDLCTip = false; } - bool DisplayNewDLCTip() { - if (!m_bSeenNewDLCTip) { - m_bSeenNewDLCTip = true; - return true; - } else - return false; + + bool AlreadySeenCreditText(const std::wstring& wstemp) { + return m_dlcController.alreadySeenCreditText(wstemp); } + void ClearNewDLCAvailable(void) { m_dlcController.clearNewDLCAvailable(); } + bool GetNewDLCAvailable() { return m_dlcController.getNewDLCAvailable(); } + void DisplayNewDLCTipAgain() { m_dlcController.displayNewDLCTipAgain(); } + bool DisplayNewDLCTip() { return m_dlcController.displayNewDLCTip(); } + // functions to store launch data, and to exit the game - required due to // possibly being on a demo disc virtual void StoreLaunchData(); @@ -509,20 +603,19 @@ public: // void InstallDefaultCape(); // attempt to install the default cape once // per game launch - // invites - // void ProcessInvite(JoinFromInviteData *pJoinData); + // invites - delegated to NetworkController void ProcessInvite(std::uint32_t dwUserIndex, std::uint32_t dwLocalUsersMask, - const INVITE_INFO* pInviteInfo); + const INVITE_INFO* pInviteInfo) { + m_networkController.processInvite(dwUserIndex, dwLocalUsersMask, pInviteInfo); + } - // Add credits for DLC installed - void AddCreditText(const wchar_t* lpStr); + // Add credits for DLC installed - delegated to DLCController + void AddCreditText(const wchar_t* lpStr) { m_dlcController.addCreditText(lpStr); } private: std::unordered_map m_GTS_Files; - VNOTIFICATIONS m_vNotifications; - public: // launch data std::uint8_t* m_pLaunchData; @@ -561,8 +654,7 @@ public: bool m_bTutorialMode; bool m_bIsAppPaused; - bool m_bChangingSessionType; - bool m_bReallyChangingSessionType; + // m_bChangingSessionType and m_bReallyChangingSessionType moved to NetworkController // trial, and trying to unlock full // version on an upsell @@ -587,9 +679,9 @@ private: static int BannedLevelDialogReturned(void* pParam, int iPad, const C4JStorage::EMessageResult); static int TexturePackDialogReturned(void* pParam, int iPad, - C4JStorage::EMessageResult result); - - void HandleButtonPresses(int iPad); + C4JStorage::EMessageResult result) { + return MenuController::texturePackDialogReturned(pParam, iPad, result); + } bool m_bResourcesLoaded; @@ -610,20 +702,13 @@ private: eGameMode m_eGameMode; // single or multiplayer - static unsigned int m_uiLastSignInData; + // GameSettingsA reference alias into GameSettingsManager + GAME_SETTINGS* (&GameSettingsA)[XUSER_MAX_COUNT] = m_gameSettingsManager.GameSettingsA; - // We've got sizeof(GAME_SETTINGS) bytes reserved at the start of the - // gamedefined data per player for settings - GAME_SETTINGS* GameSettingsA[XUSER_MAX_COUNT]; + // m_uiLastSignInData moved to NetworkController // Debug options now in m_debugOptions - // 4J : WESTY : For taking screen shots. - // bool m_bInterfaceRenderingOff; - // bool m_bHandRenderingOff; - - DisconnectPacket::eDisconnectReason m_disconnectReason; - public: virtual void RunFrame() {}; @@ -637,45 +722,53 @@ public: void SetTrialTimerStart(void); float getTrialTimer(void); - // notifications from the game for qnet - VNOTIFICATIONS* GetNotifications() { return &m_vNotifications; } + // notifications from the game for qnet - delegated to NetworkController + NetworkController::VNOTIFICATIONS* GetNotifications() { + return m_networkController.getNotifications(); + } private: - // To avoid problems with threads being kicked off from xuis that alter - // things that may be in progress within the run_middle, we'll action these - // at the end of the game loop - eXuiAction m_eXuiAction[XUSER_MAX_COUNT]; - eTMSAction m_eTMSAction[XUSER_MAX_COUNT]; - void* m_eXuiActionParam[XUSER_MAX_COUNT]; - eXuiAction m_eGlobalXuiAction; - eXuiServerAction m_eXuiServerAction[XUSER_MAX_COUNT]; - void* m_eXuiServerActionParam[XUSER_MAX_COUNT]; - eXuiServerAction m_eGlobalXuiServerAction; - - bool m_bLiveLinkRequired; static int UnlockFullExitReturned(void* pParam, int iPad, - C4JStorage::EMessageResult result); + C4JStorage::EMessageResult result) { + return MenuController::unlockFullExitReturned(pParam, iPad, result); + } static int UnlockFullSaveReturned(void* pParam, int iPad, - C4JStorage::EMessageResult result); + C4JStorage::EMessageResult result) { + return MenuController::unlockFullSaveReturned(pParam, iPad, result); + } static int UnlockFullInviteReturned(void* pParam, int iPad, - C4JStorage::EMessageResult result); + C4JStorage::EMessageResult result) { + return MenuController::unlockFullInviteReturned(pParam, iPad, result); + } static int TrialOverReturned(void* pParam, int iPad, - C4JStorage::EMessageResult result); + C4JStorage::EMessageResult result) { + return MenuController::trialOverReturned(pParam, iPad, result); + } static int ExitAndJoinFromInvite(void* pParam, int iPad, - C4JStorage::EMessageResult result); + C4JStorage::EMessageResult result) { + return NetworkController::exitAndJoinFromInvite(pParam, iPad, result); + } static int ExitAndJoinFromInviteSaveDialogReturned( - void* pParam, int iPad, C4JStorage::EMessageResult result); + void* pParam, int iPad, C4JStorage::EMessageResult result) { + return NetworkController::exitAndJoinFromInviteSaveDialogReturned(pParam, iPad, result); + } static int ExitAndJoinFromInviteAndSaveReturned( - void* pParam, int iPad, C4JStorage::EMessageResult result); + void* pParam, int iPad, C4JStorage::EMessageResult result) { + return NetworkController::exitAndJoinFromInviteAndSaveReturned(pParam, iPad, result); + } static int ExitAndJoinFromInviteDeclineSaveReturned( - void* pParam, int iPad, C4JStorage::EMessageResult result); + void* pParam, int iPad, C4JStorage::EMessageResult result) { + return NetworkController::exitAndJoinFromInviteDeclineSaveReturned(pParam, iPad, result); + } static int FatalErrorDialogReturned(void* pParam, int iPad, C4JStorage::EMessageResult result); static int WarningTrialTexturePackReturned( - void* pParam, int iPad, C4JStorage::EMessageResult result); + void* pParam, int iPad, C4JStorage::EMessageResult result) { + return NetworkController::warningTrialTexturePackReturned(pParam, iPad, result); + } - JoinFromInviteData m_InviteData; + JoinFromInviteData& m_InviteData = m_networkController.m_InviteData; // m_bDebugOptions moved to m_debugOptions // Trial timer @@ -717,10 +810,16 @@ public: float getAppTime() { return m_Time.fAppTime; } void UpdateTrialPausedTimer() { mfTrialPausedTime += m_Time.fElapsedTime; } - static int RemoteSaveThreadProc(void* lpParameter); - static void ExitGameFromRemoteSave(void* lpParameter); + static int RemoteSaveThreadProc(void* lpParameter) { + return MenuController::remoteSaveThreadProc(lpParameter); + } + static void ExitGameFromRemoteSave(void* lpParameter) { + MenuController::exitGameFromRemoteSave(lpParameter); + } static int ExitGameFromRemoteSaveDialogReturned( - void* pParam, int iPad, C4JStorage::EMessageResult result); + void* pParam, int iPad, C4JStorage::EMessageResult result) { + return MenuController::exitGameFromRemoteSaveDialogReturned(pParam, iPad, result); + } // XML public: @@ -741,16 +840,24 @@ public: MOJANG_DATA* GetMojangDataForXuid(PlayerUID xuid); static int32_t RegisterConfigValues(wchar_t* pType, int iValue); - static int32_t RegisterDLCData(wchar_t*, wchar_t*, int, uint64_t, uint64_t, - wchar_t*, unsigned int, int, - wchar_t* pDataFile); + static int32_t RegisterDLCData(wchar_t* a, wchar_t* b, int c, uint64_t d, uint64_t e, + wchar_t* f, unsigned int g, int h, + wchar_t* pDataFile) { + return DLCController::registerDLCData(a, b, c, d, e, f, g, h, pDataFile); + } bool GetDLCFullOfferIDForSkinID(const std::wstring& FirstSkin, - uint64_t* pullVal); - DLC_INFO* GetDLCInfoForTrialOfferID(uint64_t ullOfferID_Trial); - DLC_INFO* GetDLCInfoForFullOfferID(uint64_t ullOfferID_Full); + uint64_t* pullVal) { + return m_dlcController.getDLCFullOfferIDForSkinID(FirstSkin, pullVal); + } + DLC_INFO* GetDLCInfoForTrialOfferID(uint64_t ullOfferID_Trial) { + return m_dlcController.getDLCInfoForTrialOfferID(ullOfferID_Trial); + } + DLC_INFO* GetDLCInfoForFullOfferID(uint64_t ullOfferID_Full) { + return m_dlcController.getDLCInfoForFullOfferID(ullOfferID_Full); + } - unsigned int GetDLCCreditsCount(); - SCreditTextItemDef* GetDLCCredits(int iIndex); + unsigned int GetDLCCreditsCount() { return m_dlcController.getDLCCreditsCount(); } + SCreditTextItemDef* GetDLCCredits(int iIndex) { return m_dlcController.getDLCCredits(iIndex); } // TMS void ReadDLCFileFromTMS(int iPad, eTMSAction action, @@ -769,39 +876,10 @@ public: void ReadBannedList(int iPad, eTMSAction action = (eTMSAction)0, bool bCallback = false) override = 0; -private: - std::vector vDLCCredits; - - static std::unordered_map MojangData; - static std::unordered_map - DLCTextures_PackID; // for mash-up packs & texture packs - static std::unordered_map - DLCInfo_Trial; // full offerid, dlc_info - static std::unordered_map - DLCInfo_Full; // full offerid, dlc_info - static std::unordered_map - DLCInfo_SkinName; // skin name, full offer id - // bool m_bRead_TMS_XUIDS_XML; // track whether we have already read the - // TMS xuids.xml file bool m_bRead_TMS_DLCINFO_XML; // track whether - // we have already read the TMS DLC.xml file - - bool m_bDefaultCapeInstallAttempted; // have we attempted to install the - // default cape from tms - - // bool m_bwasHidingGui; // 4J Stu - Removed 1.8.2 bug fix (TU6) as not - // needed - bool m_bDLCInstallProcessCompleted; - bool m_bDLCInstallPending; - int m_iTotalDLC; - int m_iTotalDLCInstalled; + // DLC data members moved to DLCController + // Sign-in info moved to NetworkController public: - // 4J Stu - We need to be able to detect when a guest player signs in or out - // causing other guest players to change their xuid The simplest way to do - // this is to check if their guest number has changed, so store the last - // known one here 4J Stu - Now storing the whole XUSER_SIGNIN_INFO so we can - // detect xuid changes - XUSER_SIGNIN_INFO m_currentSigninInfo[XUSER_MAX_COUNT]; // void OverrideFontRenderer(bool set, bool immediate = true); // void ToggleFontRenderer() { @@ -821,32 +899,28 @@ public: bool AutosaveDue(void) { return m_saveManager.autosaveDue(); } int64_t SecondsToAutosave() { return m_saveManager.secondsToAutosave(); } -private: - unsigned int m_uiOpacityCountDown[XUSER_MAX_COUNT]; - - // DLC - bool m_bNewDLCAvailable; - bool m_bSeenNewDLCTip; - - // Host options -private: - unsigned int m_uiGameHostSettings; - static unsigned char m_szPNG[8]; + // m_uiOpacityCountDown moved to MenuController + // DLC flags moved to DLCController + // Host options - m_uiGameHostSettings moved to GameSettingsManager + unsigned int& m_uiGameHostSettings = m_gameSettingsManager.m_uiGameHostSettings; #if defined(_LARGE_WORLDS) unsigned int m_GameNewWorldSize; bool m_bGameNewWorldSizeUseMoat; unsigned int m_GameNewHellScale; #endif - unsigned int FromBigEndian(unsigned int uiValue); public: void SetGameHostOption(eGameHostOption eVal, unsigned int uiVal); void SetGameHostOption(unsigned int& uiHostSettings, eGameHostOption eVal, - unsigned int uiVal); + unsigned int uiVal) { + m_gameSettingsManager.setGameHostOption(uiHostSettings, eVal, uiVal); + } unsigned int GetGameHostOption(eGameHostOption eVal); unsigned int GetGameHostOption(unsigned int uiHostSettings, - eGameHostOption eVal); + eGameHostOption eVal) { + return m_gameSettingsManager.getGameHostOption(uiHostSettings, eVal); + } #if defined(_LARGE_WORLDS) void SetGameNewWorldSize(unsigned int newSize, bool useMoat) { @@ -864,15 +938,21 @@ public: #endif void SetResetNether(bool bResetNether) { m_bResetNether = bResetNether; } bool GetResetNether() { return m_bResetNether; } - bool CanRecordStatsAndAchievements(); + bool CanRecordStatsAndAchievements() { + return m_gameSettingsManager.canRecordStatsAndAchievements(); + } - // World seed from png image + // World seed from png image - delegated to MenuController void GetImageTextData(std::uint8_t* imageData, unsigned int imageBytes, unsigned char* seedText, unsigned int& uiHostOptions, - bool& bHostOptionsRead, std::uint32_t& uiTexturePack); + bool& bHostOptionsRead, std::uint32_t& uiTexturePack) { + m_menuController.getImageTextData(imageData, imageBytes, seedText, uiHostOptions, bHostOptionsRead, uiTexturePack); + } unsigned int CreateImageTextData(std::uint8_t* textMetadata, int64_t seed, bool hasSeed, unsigned int uiHostOptions, - unsigned int uiTexturePackId); + unsigned int uiTexturePackId) { + return m_menuController.createImageTextData(textMetadata, seed, hasSeed, uiHostOptions, uiTexturePackId); + } // Game rules GameRuleManager m_gameRules; @@ -893,50 +973,69 @@ public: } const wchar_t* GetGameRulesString(const std::wstring& key); -private: - std::uint8_t m_playerColours[MINECRAFT_NET_MAX_PLAYERS]; // An array of - // QNet small-id's - unsigned int m_playerGamePrivileges[MINECRAFT_NET_MAX_PLAYERS]; + // m_playerColours and m_playerGamePrivileges moved to NetworkController public: void UpdatePlayerInfo(std::uint8_t networkSmallId, int16_t playerColourIndex, - unsigned int playerGamePrivileges); - short GetPlayerColour(std::uint8_t networkSmallId); - unsigned int GetPlayerPrivileges(std::uint8_t networkSmallId); + unsigned int playerGamePrivileges) { + m_networkController.updatePlayerInfo(networkSmallId, playerColourIndex, playerGamePrivileges); + } + short GetPlayerColour(std::uint8_t networkSmallId) { + return m_networkController.getPlayerColour(networkSmallId); + } + unsigned int GetPlayerPrivileges(std::uint8_t networkSmallId) { + return m_networkController.getPlayerPrivileges(networkSmallId); + } std::wstring getEntityName(eINSTANCEOF type); unsigned int AddDLCRequest(eDLCMarketplaceType eContentType, - bool bPromote = false); - bool RetrieveNextDLCContent(); - bool CheckTMSDLCCanStop(); - int dlcOffersReturned(int iOfferC, std::uint32_t dwType, int iPad); - std::uint32_t GetDLCContentType(eDLCContentType eType) { - return m_dwContentTypeA[eType]; + bool bPromote = false) { + return m_dlcController.addDLCRequest(eContentType, bPromote); } - eDLCContentType Find_eDLCContentType(std::uint32_t dwType); - int GetDLCOffersCount() { return m_iDLCOfferC; } - bool DLCContentRetrieved(eDLCMarketplaceType eType); - void TickDLCOffersRetrieved(); - void ClearAndResetDLCDownloadQueue(); - bool RetrieveNextTMSPPContent(); - void TickTMSPPFilesRetrieved(); - void ClearTMSPPFilesRetrieved(); + bool RetrieveNextDLCContent() { return m_dlcController.retrieveNextDLCContent(); } + bool CheckTMSDLCCanStop() { return m_dlcController.checkTMSDLCCanStop(); } + int dlcOffersReturned(int iOfferC, std::uint32_t dwType, int iPad) { + return m_dlcController.dlcOffersReturned(iOfferC, dwType, iPad); + } + std::uint32_t GetDLCContentType(eDLCContentType eType) { + return m_dlcController.getDLCContentType(eType); + } + eDLCContentType Find_eDLCContentType(std::uint32_t dwType) { + return m_dlcController.find_eDLCContentType(dwType); + } + int GetDLCOffersCount() { return m_dlcController.getDLCOffersCount(); } + bool DLCContentRetrieved(eDLCMarketplaceType eType) { + return m_dlcController.dlcContentRetrieved(eType); + } + void TickDLCOffersRetrieved() { m_dlcController.tickDLCOffersRetrieved(); } + void ClearAndResetDLCDownloadQueue() { m_dlcController.clearAndResetDLCDownloadQueue(); } + bool RetrieveNextTMSPPContent() { return m_dlcController.retrieveNextTMSPPContent(); } + void TickTMSPPFilesRetrieved() { m_dlcController.tickTMSPPFilesRetrieved(); } + void ClearTMSPPFilesRetrieved() { m_dlcController.clearTMSPPFilesRetrieved(); } unsigned int AddTMSPPFileTypeRequest(eDLCContentType eType, - bool bPromote = false); - int GetDLCInfoTexturesOffersCount(); + bool bPromote = false) { + return m_dlcController.addTMSPPFileTypeRequest(eType, bPromote); + } + int GetDLCInfoTexturesOffersCount() { return m_dlcController.getDLCInfoTexturesOffersCount(); } static int TMSPPFileReturned(void* pParam, int iPad, int iUserData, C4JStorage::PTMSPP_FILEDATA pFileData, - const char* szFilename); - DLC_INFO* GetDLCInfoTrialOffer(int iIndex); - DLC_INFO* GetDLCInfoFullOffer(int iIndex); + const char* szFilename) { + return DLCController::tmsPPFileReturned(pParam, iPad, iUserData, pFileData, szFilename); + } + DLC_INFO* GetDLCInfoTrialOffer(int iIndex) { return m_dlcController.getDLCInfoTrialOffer(iIndex); } + DLC_INFO* GetDLCInfoFullOffer(int iIndex) { return m_dlcController.getDLCInfoFullOffer(iIndex); } - int GetDLCInfoTrialOffersCount(); - int GetDLCInfoFullOffersCount(); - bool GetDLCFullOfferIDForPackID(const int iPackID, uint64_t* pullVal); - uint64_t GetDLCInfoTexturesFullOffer(int iIndex); + int GetDLCInfoTrialOffersCount() { return m_dlcController.getDLCInfoTrialOffersCount(); } + int GetDLCInfoFullOffersCount() { return m_dlcController.getDLCInfoFullOffersCount(); } + bool GetDLCFullOfferIDForPackID(const int iPackID, uint64_t* pullVal) { + return m_dlcController.getDLCFullOfferIDForPackID(iPackID, pullVal); + } + uint64_t GetDLCInfoTexturesFullOffer(int iIndex) { + return m_dlcController.getDLCInfoTexturesFullOffer(iIndex); + } void SetCorruptSaveDeleted(bool bVal) { m_bCorruptSaveDeleted = bVal; } bool GetCorruptSaveDeleted(void) { return m_bCorruptSaveDeleted; } @@ -944,27 +1043,15 @@ public: void lockSaveNotification() { m_saveManager.lock(); } void unlockSaveNotification() { m_saveManager.unlock(); } -private: - // Download Status - - // Request current_download; - std::vector m_DLCDownloadQueue; - std::vector m_TMSPPDownloadQueue; - static std::uint32_t m_dwContentTypeA[e_Marketplace_MAX]; - int m_iDLCOfferC; - bool m_bAllDLCContentRetrieved; - bool m_bAllTMSContentRetrieved; - bool m_bTickTMSDLCFiles; - std::mutex csDLCDownloadQueue; - std::mutex csTMSPPDownloadQueue; + // Download status members moved to DLCController bool m_bCorruptSaveDeleted; std::uint8_t*& m_pBannedListFileBuffer = m_bannedListManager.m_pBannedListFileBuffer; unsigned int& m_dwBannedListFileSize = m_bannedListManager.m_dwBannedListFileSize; public: - unsigned int m_dwDLCFileSize; - std::uint8_t* m_pDLCFileBuffer; + unsigned int& m_dwDLCFileSize = m_dlcController.m_dwDLCFileSize; + std::uint8_t*& m_pDLCFileBuffer = m_dlcController.m_pDLCFileBuffer; // static int CallbackReadXuidsFileFromTMS(void* lpParam, wchar_t // *wchFilename, int iPad, bool bResult, int iAction); static int @@ -1056,7 +1143,7 @@ public: return m_localizationManager.get_xcLang(pwchLocale); } - void SetTickTMSDLCFiles(bool bVal); + void SetTickTMSDLCFiles(bool bVal) { m_dlcController.setTickTMSDLCFiles(bVal); } std::wstring getFilePath(std::uint32_t packId, std::wstring filename, bool bAddDataFolder, diff --git a/targets/app/common/GameSettingsManager.cpp b/targets/app/common/GameSettingsManager.cpp new file mode 100644 index 000000000..a26f7872f --- /dev/null +++ b/targets/app/common/GameSettingsManager.cpp @@ -0,0 +1,1449 @@ +#include "app/common/GameSettingsManager.h" + +#include "app/common/Game.h" +#include "app/common/App_Defines.h" +#include "app/common/App_enums.h" +#include "app/common/Console_Debug_enum.h" +#include "app/common/Network/GameNetworkManager.h" +#include "app/common/UI/All Platforms/UIEnums.h" +#include "app/common/UI/All Platforms/UIStructs.h" +#include "app/common/UI/Scenes/UIScene_FullscreenProgress.h" +#include "app/common/UI/Scenes/In-Game Menu Screens/UIScene_PauseMenu.h" +#include "app/linux/LinuxGame.h" +#include "app/linux/Linux_UIController.h" +#include "minecraft/GameHostOptions.h" +#include "minecraft/client/Minecraft.h" +#include "minecraft/client/Options.h" +#include "minecraft/client/gui/Gui.h" +#include "minecraft/client/multiplayer/MultiPlayerGameMode.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/server/PlayerList.h" +#include "minecraft/server/level/ServerPlayer.h" +#include "minecraft/stats/StatsCounter.h" +#include "minecraft/world/entity/player/Player.h" +#include "minecraft/world/level/tile/Tile.h" +#include "platform/sdl2/Input.h" +#include "platform/sdl2/Render.h" +#include "platform/sdl2/Storage.h" +#include "protocol/DisconnectPacket.h" +#include "app/common/Audio/SoundEngine.h" +#include "app/common/DLC/DLCPack.h" +#include "app/common/DLC/DLCManager.h" +#include "minecraft/world/level/storage/ConsoleSaveFileIO/compression.h" + +#include +#include +#include + +GameSettingsManager::GameSettingsManager() { + memset(GameSettingsA, 0, sizeof(GameSettingsA)); + m_uiGameHostSettings = 0; +} + +void GameSettingsManager::initGameSettings() { + for (int i = 0; i < XUSER_MAX_COUNT; i++) { + GameSettingsA[i] = + (GAME_SETTINGS*)ProfileManager.GetGameDefinedProfileData(i); + // clear the flag to say the settings have changed + GameSettingsA[i]->bSettingsChanged = false; + +#if defined(_WINDOWS64) + C_4JProfile::PROFILESETTINGS* pProfileSettings = + ProfileManager.GetDashboardProfileSettings(i); + memset(pProfileSettings, 0, sizeof(C_4JProfile::PROFILESETTINGS)); + setDefaultOptions(pProfileSettings, i); +#else + C_4JProfile::PROFILESETTINGS* pProfileSettings = + ProfileManager.GetDashboardProfileSettings(i); + memset(pProfileSettings, 0, sizeof(C_4JProfile::PROFILESETTINGS)); + setDefaultOptions(pProfileSettings, i); +#endif + } +} + +int GameSettingsManager::setDefaultOptions( + C_4JProfile::PROFILESETTINGS* pSettings, const int iPad) { + setGameSettings(iPad, eGameSetting_MusicVolume, DEFAULT_VOLUME_LEVEL); + setGameSettings(iPad, eGameSetting_SoundFXVolume, DEFAULT_VOLUME_LEVEL); + setGameSettings(iPad, eGameSetting_Gamma, 50); + + if (Minecraft::GetInstance()->level == nullptr) { + app.DebugPrintf("SetDefaultOptions - Difficulty = 1\n"); + setGameSettings(iPad, eGameSetting_Difficulty, 1); + } + setGameSettings(iPad, eGameSetting_Sensitivity_InGame, 100); + setGameSettings(iPad, eGameSetting_ViewBob, 1); + setGameSettings(iPad, eGameSetting_ControlScheme, 0); + setGameSettings(iPad, eGameSetting_ControlInvertLook, + (pSettings->iYAxisInversion != 0) ? 1 : 0); + setGameSettings(iPad, eGameSetting_ControlSouthPaw, + pSettings->bSwapSticks ? 1 : 0); + setGameSettings(iPad, eGameSetting_SplitScreenVertical, 0); + setGameSettings(iPad, eGameSetting_GamertagsVisible, 1); + + // Interim TU 1.6.6 + setGameSettings(iPad, eGameSetting_Sensitivity_InMenu, 100); + setGameSettings(iPad, eGameSetting_DisplaySplitscreenGamertags, 1); + setGameSettings(iPad, eGameSetting_Hints, 1); + setGameSettings(iPad, eGameSetting_Autosave, 2); + setGameSettings(iPad, eGameSetting_Tooltips, 1); + setGameSettings(iPad, eGameSetting_InterfaceOpacity, 80); + + // TU 5 + setGameSettings(iPad, eGameSetting_Clouds, 1); + setGameSettings(iPad, eGameSetting_Online, 1); + setGameSettings(iPad, eGameSetting_InviteOnly, 0); + setGameSettings(iPad, eGameSetting_FriendsOfFriends, 1); + + // TU 6 + setGameSettings(iPad, eGameSetting_BedrockFog, 0); + setGameSettings(iPad, eGameSetting_DisplayHUD, 1); + setGameSettings(iPad, eGameSetting_DisplayHand, 1); + + // TU 7 + setGameSettings(iPad, eGameSetting_CustomSkinAnim, 1); + + // TU 9 + setGameSettings(iPad, eGameSetting_DeathMessages, 1); + setGameSettings(iPad, eGameSetting_UISize, 1); + setGameSettings(iPad, eGameSetting_UISizeSplitscreen, 2); + setGameSettings(iPad, eGameSetting_AnimatedCharacter, 1); + + // TU 12 + GameSettingsA[iPad]->ucCurrentFavoriteSkinPos = 0; + for (int i = 0; i < MAX_FAVORITE_SKINS; i++) { + GameSettingsA[iPad]->uiFavoriteSkinA[i] = 0xFFFFFFFF; + } + + // TU 13 + GameSettingsA[iPad]->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + + // 1.6.4 + app.SetGameHostOption(eGameHostOption_MobGriefing, 1); + app.SetGameHostOption(eGameHostOption_KeepInventory, 0); + app.SetGameHostOption(eGameHostOption_DoMobSpawning, 1); + app.SetGameHostOption(eGameHostOption_DoMobLoot, 1); + app.SetGameHostOption(eGameHostOption_DoTileDrops, 1); + app.SetGameHostOption(eGameHostOption_NaturalRegeneration, 1); + app.SetGameHostOption(eGameHostOption_DoDaylightCycle, 1); + + // PS3DEC13 + setGameSettings(iPad, eGameSetting_PS3_EULA_Read, 0); + + if (!app.GetGameStarted()) { + GameSettingsA[iPad]->ucLanguage = + MINECRAFT_LANGUAGE_DEFAULT; + GameSettingsA[iPad]->ucLocale = + MINECRAFT_LANGUAGE_DEFAULT; + } + + return 0; +} + +int GameSettingsManager::defaultOptionsCallback( + void* pParam, C_4JProfile::PROFILESETTINGS* pSettings, const int iPad) { + Game* pApp = (Game*)pParam; + + pApp->DebugPrintf("Setting default options for player %d", iPad); + pApp->SetAction(iPad, eAppAction_SetDefaultOptions, (void*)pSettings); + + return 0; +} + +int GameSettingsManager::oldProfileVersionCallback( + void* pParam, unsigned char* pucData, const unsigned short usVersion, + const int iPad) { + switch (usVersion) { + case PROFILE_VERSION_8: { + GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; + pGameSettings->uiBitmaskValues |= GAMESETTING_DISPLAYUPDATEMSG; + pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + pGameSettings->uiBitmaskValues &= ~GAMESETTING_PS3EULAREAD; + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; + } break; + case PROFILE_VERSION_9: { + GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; + pGameSettings->uiBitmaskValues |= GAMESETTING_DISPLAYUPDATEMSG; + pGameSettings->uiBitmaskValues &= ~GAMESETTING_PS3EULAREAD; + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; + } break; + case PROFILE_VERSION_10: { + GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; + pGameSettings->uiBitmaskValues |= GAMESETTING_DISPLAYUPDATEMSG; + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; + } break; + case PROFILE_VERSION_11: { + GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; + pGameSettings->uiBitmaskValues |= GAMESETTING_DISPLAYUPDATEMSG; + } break; + case PROFILE_VERSION_12: { + GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; + pGameSettings->uiBitmaskValues |= GAMESETTING_DISPLAYUPDATEMSG; + } break; + default: { + app.DebugPrintf( + "Don't know what to do with this profile version!\n"); + + GAME_SETTINGS* pGameSettings = (GAME_SETTINGS*)pucData; + pGameSettings->ucMenuSensitivity = 100; + pGameSettings->ucInterfaceOpacity = 80; + pGameSettings->usBitmaskValues |= 0x0200; + pGameSettings->usBitmaskValues |= 0x0400; + pGameSettings->usBitmaskValues |= 0x1000; + pGameSettings->usBitmaskValues |= 0x8000; + + pGameSettings->uiBitmaskValues = 0L; + pGameSettings->uiBitmaskValues |= GAMESETTING_CLOUDS; + pGameSettings->uiBitmaskValues |= GAMESETTING_ONLINE; + pGameSettings->uiBitmaskValues |= GAMESETTING_FRIENDSOFFRIENDS; + pGameSettings->uiBitmaskValues |= GAMESETTING_DISPLAYUPDATEMSG; + pGameSettings->uiBitmaskValues &= ~GAMESETTING_BEDROCKFOG; + pGameSettings->uiBitmaskValues |= GAMESETTING_DISPLAYHUD; + pGameSettings->uiBitmaskValues |= GAMESETTING_DISPLAYHAND; + pGameSettings->uiBitmaskValues |= GAMESETTING_CUSTOMSKINANIM; + pGameSettings->uiBitmaskValues |= GAMESETTING_DEATHMESSAGES; + pGameSettings->uiBitmaskValues |= + (GAMESETTING_UISIZE & 0x00000800); + pGameSettings->uiBitmaskValues |= + (GAMESETTING_UISIZE_SPLITSCREEN & 0x00004000); + pGameSettings->uiBitmaskValues |= GAMESETTING_ANIMATEDCHARACTER; + for (int i = 0; i < MAX_FAVORITE_SKINS; i++) { + pGameSettings->uiFavoriteSkinA[i] = 0xFFFFFFFF; + } + pGameSettings->ucCurrentFavoriteSkinPos = 0; + pGameSettings->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + pGameSettings->uiBitmaskValues &= ~GAMESETTING_PS3EULAREAD; + pGameSettings->ucLanguage = MINECRAFT_LANGUAGE_DEFAULT; + } break; + } + + return 0; +} + +void GameSettingsManager::applyGameSettingsChanged(int iPad) { + actionGameSettings(iPad, eGameSetting_MusicVolume); + actionGameSettings(iPad, eGameSetting_SoundFXVolume); + actionGameSettings(iPad, eGameSetting_Gamma); + actionGameSettings(iPad, eGameSetting_Difficulty); + actionGameSettings(iPad, eGameSetting_Sensitivity_InGame); + actionGameSettings(iPad, eGameSetting_ViewBob); + actionGameSettings(iPad, eGameSetting_ControlScheme); + actionGameSettings(iPad, eGameSetting_ControlInvertLook); + actionGameSettings(iPad, eGameSetting_ControlSouthPaw); + actionGameSettings(iPad, eGameSetting_SplitScreenVertical); + actionGameSettings(iPad, eGameSetting_GamertagsVisible); + + // Interim TU 1.6.6 + actionGameSettings(iPad, eGameSetting_Sensitivity_InMenu); + actionGameSettings(iPad, eGameSetting_DisplaySplitscreenGamertags); + actionGameSettings(iPad, eGameSetting_Hints); + actionGameSettings(iPad, eGameSetting_InterfaceOpacity); + actionGameSettings(iPad, eGameSetting_Tooltips); + + actionGameSettings(iPad, eGameSetting_Clouds); + actionGameSettings(iPad, eGameSetting_BedrockFog); + actionGameSettings(iPad, eGameSetting_DisplayHUD); + actionGameSettings(iPad, eGameSetting_DisplayHand); + actionGameSettings(iPad, eGameSetting_CustomSkinAnim); + actionGameSettings(iPad, eGameSetting_DeathMessages); + actionGameSettings(iPad, eGameSetting_UISize); + actionGameSettings(iPad, eGameSetting_UISizeSplitscreen); + actionGameSettings(iPad, eGameSetting_AnimatedCharacter); + + actionGameSettings(iPad, eGameSetting_PS3_EULA_Read); +} + +void GameSettingsManager::actionGameSettings(int iPad, eGameSetting eVal) { + Minecraft* pMinecraft = Minecraft::GetInstance(); + switch (eVal) { + case eGameSetting_MusicVolume: + if (iPad == ProfileManager.GetPrimaryPad()) { + pMinecraft->options->set( + Options::Option::MUSIC, + ((float)GameSettingsA[iPad]->ucMusicVolume) / 100.0f); + } + break; + case eGameSetting_SoundFXVolume: + if (iPad == ProfileManager.GetPrimaryPad()) { + pMinecraft->options->set( + Options::Option::SOUND, + ((float)GameSettingsA[iPad]->ucSoundFXVolume) / 100.0f); + } + break; + case eGameSetting_Gamma: + if (iPad == ProfileManager.GetPrimaryPad()) { + float fVal = ((float)GameSettingsA[iPad]->ucGamma) * 327.68f; + RenderManager.UpdateGamma((unsigned short)fVal); + } + break; + case eGameSetting_Difficulty: + if (iPad == ProfileManager.GetPrimaryPad()) { + pMinecraft->options->toggle( + Options::Option::DIFFICULTY, + GameSettingsA[iPad]->usBitmaskValues & 0x03); + app.DebugPrintf("Difficulty toggle to %d\n", + GameSettingsA[iPad]->usBitmaskValues & 0x03); + + app.SetGameHostOption(eGameHostOption_Difficulty, + pMinecraft->options->difficulty); + + bool bInGame = pMinecraft->level != nullptr; + + if (bInGame && g_NetworkManager.IsHost() && + (iPad == ProfileManager.GetPrimaryPad())) { + app.SetXuiServerAction( + iPad, eXuiServerAction_ServerSettingChanged_Difficulty); + } + } else { + app.DebugPrintf( + "NOT ACTIONING DIFFICULTY - Primary pad is %d, This pad is " + "%d\n", + ProfileManager.GetPrimaryPad(), iPad); + } + break; + case eGameSetting_Sensitivity_InGame: + pMinecraft->options->set( + Options::Option::SENSITIVITY, + ((float)GameSettingsA[iPad]->ucSensitivity) / 100.0f); + break; + case eGameSetting_ViewBob: + break; + case eGameSetting_ControlScheme: + InputManager.SetJoypadMapVal( + iPad, (GameSettingsA[iPad]->usBitmaskValues & 0x30) >> 4); + break; + case eGameSetting_ControlInvertLook: + break; + case eGameSetting_ControlSouthPaw: + if (GameSettingsA[iPad]->usBitmaskValues & 0x80) { + InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_LX, + AXIS_MAP_RX); + InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_LY, + AXIS_MAP_RY); + InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_RX, + AXIS_MAP_LX); + InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_RY, + AXIS_MAP_LY); + InputManager.SetJoypadStickTriggerMap(iPad, TRIGGER_MAP_0, + TRIGGER_MAP_1); + InputManager.SetJoypadStickTriggerMap(iPad, TRIGGER_MAP_1, + TRIGGER_MAP_0); + } else { + InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_LX, + AXIS_MAP_LX); + InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_LY, + AXIS_MAP_LY); + InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_RX, + AXIS_MAP_RX); + InputManager.SetJoypadStickAxisMap(iPad, AXIS_MAP_RY, + AXIS_MAP_RY); + InputManager.SetJoypadStickTriggerMap(iPad, TRIGGER_MAP_0, + TRIGGER_MAP_0); + InputManager.SetJoypadStickTriggerMap(iPad, TRIGGER_MAP_1, + TRIGGER_MAP_1); + } + break; + case eGameSetting_SplitScreenVertical: + if (iPad == ProfileManager.GetPrimaryPad()) { + pMinecraft->updatePlayerViewportAssignments(); + } + break; + case eGameSetting_GamertagsVisible: { + bool bInGame = pMinecraft->level != nullptr; + + // Game Host only + if (bInGame && g_NetworkManager.IsHost() && + (iPad == ProfileManager.GetPrimaryPad())) { + app.SetGameHostOption( + eGameHostOption_Gamertags, + ((GameSettingsA[iPad]->usBitmaskValues & 0x0008) != 0) ? 1 + : 0); + app.SetXuiServerAction( + iPad, eXuiServerAction_ServerSettingChanged_Gamertags); + + PlayerList* players = + MinecraftServer::getInstance()->getPlayerList(); + for (auto it3 = players->players.begin(); + it3 != players->players.end(); ++it3) { + std::shared_ptr decorationPlayer = *it3; + decorationPlayer->setShowOnMaps( + (app.GetGameHostOption(eGameHostOption_Gamertags) != 0) + ? true + : false); + } + } + } break; + case eGameSetting_Sensitivity_InMenu: + break; + case eGameSetting_DisplaySplitscreenGamertags: + for (std::uint8_t idx = 0; idx < XUSER_MAX_COUNT; ++idx) { + if (pMinecraft->localplayers[idx] != nullptr) { + if (pMinecraft->localplayers[idx]->m_iScreenSection == + C4JRender::VIEWPORT_TYPE_FULLSCREEN) { + ui.DisplayGamertag(idx, false); + } else { + ui.DisplayGamertag(idx, true); + } + } + } + break; + case eGameSetting_InterfaceOpacity: + ui.RefreshTooltips(iPad); + break; + case eGameSetting_Hints: + break; + case eGameSetting_Tooltips: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x8000) != 0) { + ui.SetEnableTooltips(iPad, true); + } else { + ui.SetEnableTooltips(iPad, false); + } + break; + case eGameSetting_Clouds: + break; + case eGameSetting_Online: + break; + case eGameSetting_InviteOnly: + break; + case eGameSetting_FriendsOfFriends: + break; + case eGameSetting_BedrockFog: { + bool bInGame = pMinecraft->level != nullptr; + + if (bInGame && g_NetworkManager.IsHost() && + (iPad == ProfileManager.GetPrimaryPad())) { + app.SetGameHostOption( + eGameHostOption_BedrockFog, + getGameSettings(iPad, eGameSetting_BedrockFog) ? 1 : 0); + app.SetXuiServerAction( + iPad, eXuiServerAction_ServerSettingChanged_BedrockFog); + } + } break; + case eGameSetting_DisplayHUD: + break; + case eGameSetting_DisplayHand: + break; + case eGameSetting_CustomSkinAnim: + break; + case eGameSetting_DeathMessages: + break; + case eGameSetting_UISize: + break; + case eGameSetting_UISizeSplitscreen: + break; + case eGameSetting_AnimatedCharacter: + break; + case eGameSetting_PS3_EULA_Read: + break; + case eGameSetting_PSVita_NetworkModeAdhoc: + break; + default: + break; + } +} + +void GameSettingsManager::hideMashupPackWorld(int iPad, + unsigned int iMashupPackID) { + unsigned int uiPackID = iMashupPackID - 1024; + GameSettingsA[iPad]->uiMashUpPackWorldsDisplay &= ~(1 << uiPackID); + GameSettingsA[iPad]->bSettingsChanged = true; +} + +void GameSettingsManager::enableMashupPackWorlds(int iPad) { + GameSettingsA[iPad]->uiMashUpPackWorldsDisplay = 0xFFFFFFFF; + GameSettingsA[iPad]->bSettingsChanged = true; +} + +unsigned int GameSettingsManager::getMashupPackWorlds(int iPad) { + return GameSettingsA[iPad]->uiMashUpPackWorldsDisplay; +} + +void GameSettingsManager::setMinecraftLanguage(int iPad, + unsigned char ucLanguage) { + GameSettingsA[iPad]->ucLanguage = ucLanguage; + GameSettingsA[iPad]->bSettingsChanged = true; +} + +unsigned char GameSettingsManager::getMinecraftLanguage(int iPad) { + if (GameSettingsA[iPad] == nullptr) { + return 0; + } else { + return GameSettingsA[iPad]->ucLanguage; + } +} + +void GameSettingsManager::setMinecraftLocale(int iPad, + unsigned char ucLocale) { + GameSettingsA[iPad]->ucLocale = ucLocale; + GameSettingsA[iPad]->bSettingsChanged = true; +} + +unsigned char GameSettingsManager::getMinecraftLocale(int iPad) { + if (GameSettingsA[iPad] == nullptr) { + return 0; + } else { + return GameSettingsA[iPad]->ucLocale; + } +} + +void GameSettingsManager::setGameSettings(int iPad, eGameSetting eVal, + unsigned char ucVal) { + switch (eVal) { + case eGameSetting_MusicVolume: + if (GameSettingsA[iPad]->ucMusicVolume != ucVal) { + GameSettingsA[iPad]->ucMusicVolume = ucVal; + if (iPad == ProfileManager.GetPrimaryPad()) { + actionGameSettings(iPad, eVal); + } + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_SoundFXVolume: + if (GameSettingsA[iPad]->ucSoundFXVolume != ucVal) { + GameSettingsA[iPad]->ucSoundFXVolume = ucVal; + if (iPad == ProfileManager.GetPrimaryPad()) { + actionGameSettings(iPad, eVal); + } + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_Gamma: + if (GameSettingsA[iPad]->ucGamma != ucVal) { + GameSettingsA[iPad]->ucGamma = ucVal; + if (iPad == ProfileManager.GetPrimaryPad()) { + actionGameSettings(iPad, eVal); + } + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_Difficulty: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x03) != + (ucVal & 0x03)) { + GameSettingsA[iPad]->usBitmaskValues &= ~0x03; + GameSettingsA[iPad]->usBitmaskValues |= ucVal & 0x03; + if (iPad == ProfileManager.GetPrimaryPad()) { + actionGameSettings(iPad, eVal); + } + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_Sensitivity_InGame: + if (GameSettingsA[iPad]->ucSensitivity != ucVal) { + GameSettingsA[iPad]->ucSensitivity = ucVal; + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_ViewBob: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x0004) != + ((ucVal & 0x01) << 2)) { + if (ucVal != 0) { + GameSettingsA[iPad]->usBitmaskValues |= 0x0004; + } else { + GameSettingsA[iPad]->usBitmaskValues &= ~0x0004; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_ControlScheme: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x30) != + ((ucVal & 0x03) << 4)) { + GameSettingsA[iPad]->usBitmaskValues &= ~0x0030; + if (ucVal != 0) { + GameSettingsA[iPad]->usBitmaskValues |= (ucVal & 0x03) << 4; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_ControlInvertLook: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x0040) != + ((ucVal & 0x01) << 6)) { + if (ucVal != 0) { + GameSettingsA[iPad]->usBitmaskValues |= 0x0040; + } else { + GameSettingsA[iPad]->usBitmaskValues &= ~0x0040; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_ControlSouthPaw: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x0080) != + ((ucVal & 0x01) << 7)) { + if (ucVal != 0) { + GameSettingsA[iPad]->usBitmaskValues |= 0x0080; + } else { + GameSettingsA[iPad]->usBitmaskValues &= ~0x0080; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_SplitScreenVertical: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x0100) != + ((ucVal & 0x01) << 8)) { + if (ucVal != 0) { + GameSettingsA[iPad]->usBitmaskValues |= 0x0100; + } else { + GameSettingsA[iPad]->usBitmaskValues &= ~0x0100; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_GamertagsVisible: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x0008) != + ((ucVal & 0x01) << 3)) { + if (ucVal != 0) { + GameSettingsA[iPad]->usBitmaskValues |= 0x0008; + } else { + GameSettingsA[iPad]->usBitmaskValues &= ~0x0008; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_Sensitivity_InMenu: + if (GameSettingsA[iPad]->ucMenuSensitivity != ucVal) { + GameSettingsA[iPad]->ucMenuSensitivity = ucVal; + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_DisplaySplitscreenGamertags: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x0200) != + ((ucVal & 0x01) << 9)) { + if (ucVal != 0) { + GameSettingsA[iPad]->usBitmaskValues |= 0x0200; + } else { + GameSettingsA[iPad]->usBitmaskValues &= ~0x0200; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_Hints: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x0400) != + ((ucVal & 0x01) << 10)) { + if (ucVal != 0) { + GameSettingsA[iPad]->usBitmaskValues |= 0x0400; + } else { + GameSettingsA[iPad]->usBitmaskValues &= ~0x0400; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_Autosave: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x7800) != + ((ucVal & 0x0F) << 11)) { + GameSettingsA[iPad]->usBitmaskValues &= ~0x7800; + if (ucVal != 0) { + GameSettingsA[iPad]->usBitmaskValues |= (ucVal & 0x0F) + << 11; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_Tooltips: + if ((GameSettingsA[iPad]->usBitmaskValues & 0x8000) != + ((ucVal & 0x01) << 15)) { + if (ucVal != 0) { + GameSettingsA[iPad]->usBitmaskValues |= 0x8000; + } else { + GameSettingsA[iPad]->usBitmaskValues &= ~0x8000; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_InterfaceOpacity: + if (GameSettingsA[iPad]->ucInterfaceOpacity != ucVal) { + GameSettingsA[iPad]->ucInterfaceOpacity = ucVal; + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_Clouds: + if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CLOUDS) != + (ucVal & 0x01)) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_CLOUDS; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_CLOUDS; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_Online: + if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_ONLINE) != + (ucVal & 0x01) << 1) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= GAMESETTING_ONLINE; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_ONLINE; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_InviteOnly: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_INVITEONLY) != (ucVal & 0x01) << 2) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= + GAMESETTING_INVITEONLY; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_INVITEONLY; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_FriendsOfFriends: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_FRIENDSOFFRIENDS) != (ucVal & 0x01) << 3) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= + GAMESETTING_FRIENDSOFFRIENDS; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_FRIENDSOFFRIENDS; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_DisplayUpdateMessage: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_DISPLAYUPDATEMSG) != (ucVal & 0x03) << 4) { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_DISPLAYUPDATEMSG; + if (ucVal > 0) { + GameSettingsA[iPad]->uiBitmaskValues |= (ucVal & 0x03) << 4; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_BedrockFog: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_BEDROCKFOG) != (ucVal & 0x01) << 6) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= + GAMESETTING_BEDROCKFOG; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_BEDROCKFOG; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_DisplayHUD: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_DISPLAYHUD) != (ucVal & 0x01) << 7) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= + GAMESETTING_DISPLAYHUD; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_DISPLAYHUD; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_DisplayHand: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_DISPLAYHAND) != (ucVal & 0x01) << 8) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= + GAMESETTING_DISPLAYHAND; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_DISPLAYHAND; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_CustomSkinAnim: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_CUSTOMSKINANIM) != (ucVal & 0x01) << 9) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= + GAMESETTING_CUSTOMSKINANIM; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_CUSTOMSKINANIM; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_DeathMessages: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_DEATHMESSAGES) != (ucVal & 0x01) << 10) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= + GAMESETTING_DEATHMESSAGES; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_DEATHMESSAGES; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_UISize: + if ((GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_UISIZE) != + ((ucVal & 0x03) << 11)) { + GameSettingsA[iPad]->uiBitmaskValues &= ~GAMESETTING_UISIZE; + if (ucVal != 0) { + GameSettingsA[iPad]->uiBitmaskValues |= (ucVal & 0x03) + << 11; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_UISizeSplitscreen: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_UISIZE_SPLITSCREEN) != ((ucVal & 0x03) << 13)) { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_UISIZE_SPLITSCREEN; + if (ucVal != 0) { + GameSettingsA[iPad]->uiBitmaskValues |= (ucVal & 0x03) + << 13; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_AnimatedCharacter: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_ANIMATEDCHARACTER) != (ucVal & 0x01) << 15) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= + GAMESETTING_ANIMATEDCHARACTER; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_ANIMATEDCHARACTER; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_PS3_EULA_Read: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_PS3EULAREAD) != (ucVal & 0x01) << 16) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= + GAMESETTING_PS3EULAREAD; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_PS3EULAREAD; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + case eGameSetting_PSVita_NetworkModeAdhoc: + if ((GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_PSVITANETWORKMODEADHOC) != (ucVal & 0x01) << 17) { + if (ucVal == 1) { + GameSettingsA[iPad]->uiBitmaskValues |= + GAMESETTING_PSVITANETWORKMODEADHOC; + } else { + GameSettingsA[iPad]->uiBitmaskValues &= + ~GAMESETTING_PSVITANETWORKMODEADHOC; + } + actionGameSettings(iPad, eVal); + GameSettingsA[iPad]->bSettingsChanged = true; + } + break; + } +} + +unsigned char GameSettingsManager::getGameSettings(eGameSetting eVal) { + int iPad = ProfileManager.GetPrimaryPad(); + return getGameSettings(iPad, eVal); +} + +unsigned char GameSettingsManager::getGameSettings(int iPad, + eGameSetting eVal) { + switch (eVal) { + case eGameSetting_MusicVolume: + return GameSettingsA[iPad]->ucMusicVolume; + case eGameSetting_SoundFXVolume: + return GameSettingsA[iPad]->ucSoundFXVolume; + case eGameSetting_Gamma: + return GameSettingsA[iPad]->ucGamma; + case eGameSetting_Difficulty: + return GameSettingsA[iPad]->usBitmaskValues & 0x0003; + case eGameSetting_Sensitivity_InGame: + return GameSettingsA[iPad]->ucSensitivity; + case eGameSetting_ViewBob: + return ((GameSettingsA[iPad]->usBitmaskValues & 0x0004) >> 2); + case eGameSetting_GamertagsVisible: + return ((GameSettingsA[iPad]->usBitmaskValues & 0x0008) >> 3); + case eGameSetting_ControlScheme: + return ((GameSettingsA[iPad]->usBitmaskValues & 0x0030) >> 4); + case eGameSetting_ControlInvertLook: + return ((GameSettingsA[iPad]->usBitmaskValues & 0x0040) >> 6); + case eGameSetting_ControlSouthPaw: + return ((GameSettingsA[iPad]->usBitmaskValues & 0x0080) >> 7); + case eGameSetting_SplitScreenVertical: + return ((GameSettingsA[iPad]->usBitmaskValues & 0x0100) >> 8); + case eGameSetting_Sensitivity_InMenu: + return GameSettingsA[iPad]->ucMenuSensitivity; + case eGameSetting_DisplaySplitscreenGamertags: + return ((GameSettingsA[iPad]->usBitmaskValues & 0x0200) >> 9); + case eGameSetting_Hints: + return ((GameSettingsA[iPad]->usBitmaskValues & 0x0400) >> 10); + case eGameSetting_Autosave: { + unsigned char ucVal = + (GameSettingsA[iPad]->usBitmaskValues & 0x7800) >> 11; + return ucVal; + } + case eGameSetting_Tooltips: + return ((GameSettingsA[iPad]->usBitmaskValues & 0x8000) >> 15); + case eGameSetting_InterfaceOpacity: + return GameSettingsA[iPad]->ucInterfaceOpacity; + case eGameSetting_Clouds: + return (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_CLOUDS); + case eGameSetting_Online: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_ONLINE) >> + 1; + case eGameSetting_InviteOnly: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_INVITEONLY) >> + 2; + case eGameSetting_FriendsOfFriends: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_FRIENDSOFFRIENDS) >> + 3; + case eGameSetting_DisplayUpdateMessage: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_DISPLAYUPDATEMSG) >> + 4; + case eGameSetting_BedrockFog: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_BEDROCKFOG) >> + 6; + case eGameSetting_DisplayHUD: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_DISPLAYHUD) >> + 7; + case eGameSetting_DisplayHand: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_DISPLAYHAND) >> + 8; + case eGameSetting_CustomSkinAnim: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_CUSTOMSKINANIM) >> + 9; + case eGameSetting_DeathMessages: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_DEATHMESSAGES) >> + 10; + case eGameSetting_UISize: { + unsigned char ucVal = + (GameSettingsA[iPad]->uiBitmaskValues & GAMESETTING_UISIZE) >> + 11; + return ucVal; + } + case eGameSetting_UISizeSplitscreen: { + unsigned char ucVal = (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_UISIZE_SPLITSCREEN) >> + 13; + return ucVal; + } + case eGameSetting_AnimatedCharacter: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_ANIMATEDCHARACTER) >> + 15; + case eGameSetting_PS3_EULA_Read: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_PS3EULAREAD) >> + 16; + case eGameSetting_PSVita_NetworkModeAdhoc: + return (GameSettingsA[iPad]->uiBitmaskValues & + GAMESETTING_PSVITANETWORKMODEADHOC) >> + 17; + } + return 0; +} + +void GameSettingsManager::checkGameSettingsChanged(bool bOverride5MinuteTimer, + int iPad) { + if (iPad == XUSER_INDEX_ANY) { + for (int i = 0; i < XUSER_MAX_COUNT; i++) { + if (GameSettingsA[i]->bSettingsChanged) { + ProfileManager.WriteToProfile(i, true, bOverride5MinuteTimer); + GameSettingsA[i]->bSettingsChanged = false; + } + } + } else { + if (GameSettingsA[iPad]->bSettingsChanged) { + ProfileManager.WriteToProfile(iPad, true, bOverride5MinuteTimer); + GameSettingsA[iPad]->bSettingsChanged = false; + } + } +} + +void GameSettingsManager::clearGameSettingsChangedFlag(int iPad) { + GameSettingsA[iPad]->bSettingsChanged = false; +} + +#if !defined(_DEBUG_MENUS_ENABLED) +unsigned int GameSettingsManager::getGameSettingsDebugMask( + int iPad, bool bOverridePlayer) { + return 0; +} + +void GameSettingsManager::setGameSettingsDebugMask(int iPad, + unsigned int uiVal) {} + +void GameSettingsManager::actionDebugMask(int iPad, bool bSetAllClear) {} + +#else + +unsigned int GameSettingsManager::getGameSettingsDebugMask( + int iPad, bool bOverridePlayer) { + if (iPad == -1) { + iPad = ProfileManager.GetPrimaryPad(); + } + if (iPad < 0) iPad = 0; + + std::shared_ptr player = + Minecraft::GetInstance()->localplayers[iPad]; + + if (bOverridePlayer || player == nullptr) { + return GameSettingsA[iPad]->uiDebugBitmask; + } else { + return player->GetDebugOptions(); + } +} + +void GameSettingsManager::setGameSettingsDebugMask(int iPad, + unsigned int uiVal) { +#if !defined(_CONTENT_PACKAGE) + GameSettingsA[iPad]->bSettingsChanged = true; + GameSettingsA[iPad]->uiDebugBitmask = uiVal; + + std::shared_ptr player = + Minecraft::GetInstance()->localplayers[iPad]; + + if (player) { + Minecraft::GetInstance()->localgameModes[iPad]->handleDebugOptions( + uiVal, player); + } +#endif +} + +void GameSettingsManager::actionDebugMask(int iPad, bool bSetAllClear) { + unsigned int ulBitmask = app.GetGameSettingsDebugMask(iPad); + + if (bSetAllClear) ulBitmask = 0L; + + if (ProfileManager.GetPrimaryPad() != iPad) return; + + for (int i = 0; i < eDebugSetting_Max; i++) { + switch (i) { + case eDebugSetting_LoadSavesFromDisk: + if (ulBitmask & (1 << i)) { + app.SetLoadSavesFromFolderEnabled(true); + } else { + app.SetLoadSavesFromFolderEnabled(false); + } + break; + case eDebugSetting_WriteSavesToDisk: + if (ulBitmask & (1 << i)) { + app.SetWriteSavesToFolderEnabled(true); + } else { + app.SetWriteSavesToFolderEnabled(false); + } + break; + case eDebugSetting_FreezePlayers: + if (ulBitmask & (1 << i)) { + app.SetFreezePlayers(true); + } else { + app.SetFreezePlayers(false); + } + break; + case eDebugSetting_Safearea: + if (ulBitmask & (1 << i)) { + app.ShowSafeArea(true); + } else { + app.ShowSafeArea(false); + } + break; + case eDebugSetting_ShowUIConsole: + if (ulBitmask & (1 << i)) { + ui.ShowUIDebugConsole(true); + } else { + ui.ShowUIDebugConsole(false); + } + break; + case eDebugSetting_ShowUIMarketingGuide: + if (ulBitmask & (1 << i)) { + ui.ShowUIDebugMarketingGuide(true); + } else { + ui.ShowUIDebugMarketingGuide(false); + } + break; + case eDebugSetting_MobsDontAttack: + if (ulBitmask & (1 << i)) { + app.SetMobsDontAttackEnabled(true); + } else { + app.SetMobsDontAttackEnabled(false); + } + break; + case eDebugSetting_UseDpadForDebug: + if (ulBitmask & (1 << i)) { + app.SetUseDPadForDebug(true); + } else { + app.SetUseDPadForDebug(false); + } + break; + case eDebugSetting_MobsDontTick: + if (ulBitmask & (1 << i)) { + app.SetMobsDontTickEnabled(true); + } else { + app.SetMobsDontTickEnabled(false); + } + break; + } + } +} +#endif + +void GameSettingsManager::setSpecialTutorialCompletionFlag(int iPad, + int index) { + if (index >= 0 && index < 32 && GameSettingsA[iPad] != nullptr) { + GameSettingsA[iPad]->uiSpecialTutorialBitmask |= (1 << index); + } +} + +int GameSettingsManager::displaySavingMessage( + C4JStorage::ESavingMessage eVal, int iPad) { + ui.ShowSavingMessage(iPad, eVal); + return 0; +} + +void GameSettingsManager::setActionConfirmed(void* param) { + XuiActionParam* actionInfo = (XuiActionParam*)param; + app.SetAction(actionInfo->iPad, actionInfo->action); +} + +void GameSettingsManager::handleButtonPresses() { + for (int i = 0; i < 4; i++) { + handleButtonPresses(i); + } +} + +void GameSettingsManager::handleButtonPresses(int iPad) { + // Stub - button presses are handled elsewhere now +} + +void GameSettingsManager::setGameHostOption(unsigned int& uiHostSettings, + eGameHostOption eVal, + unsigned int uiVal) { + switch (eVal) { + case eGameHostOption_FriendsOfFriends: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS; + } + break; + case eGameHostOption_Difficulty: + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DIFFICULTY; + uiHostSettings |= (GAME_HOST_OPTION_BITMASK_DIFFICULTY & uiVal); + break; + case eGameHostOption_Gamertags: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_GAMERTAGS; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_GAMERTAGS; + } + break; + case eGameHostOption_GameType: + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_GAMETYPE; + uiHostSettings |= + (GAME_HOST_OPTION_BITMASK_GAMETYPE & (uiVal << 4)); + break; + case eGameHostOption_LevelType: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_LEVELTYPE; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_LEVELTYPE; + } + break; + case eGameHostOption_Structures: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_STRUCTURES; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_STRUCTURES; + } + break; + case eGameHostOption_BonusChest: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_BONUSCHEST; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_BONUSCHEST; + } + break; + case eGameHostOption_HasBeenInCreative: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_BEENINCREATIVE; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_BEENINCREATIVE; + } + break; + case eGameHostOption_PvP: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_PVP; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_PVP; + } + break; + case eGameHostOption_TrustPlayers: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS; + } + break; + case eGameHostOption_TNT: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_TNT; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_TNT; + } + break; + case eGameHostOption_FireSpreads: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_FIRESPREADS; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_FIRESPREADS; + } + break; + case eGameHostOption_CheatsEnabled: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTFLY; + uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTHUNGER; + uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTFLY; + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTHUNGER; + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; + } + break; + case eGameHostOption_HostCanFly: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTFLY; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTFLY; + } + break; + case eGameHostOption_HostCanChangeHunger: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTHUNGER; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTHUNGER; + } + break; + case eGameHostOption_HostCanBeInvisible: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE; + } + break; + case eGameHostOption_BedrockFog: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_BEDROCKFOG; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_BEDROCKFOG; + } + break; + case eGameHostOption_DisableSaving: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_DISABLESAVE; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DISABLESAVE; + } + break; + case eGameHostOption_WasntSaveOwner: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_NOTOWNER; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_NOTOWNER; + } + break; + case eGameHostOption_MobGriefing: + if (uiVal != 1) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_MOBGRIEFING; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_MOBGRIEFING; + } + break; + case eGameHostOption_KeepInventory: + if (uiVal != 0) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_KEEPINVENTORY; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_KEEPINVENTORY; + } + break; + case eGameHostOption_DoMobSpawning: + if (uiVal != 1) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING; + } + break; + case eGameHostOption_DoMobLoot: + if (uiVal != 1) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOMOBLOOT; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOMOBLOOT; + } + break; + case eGameHostOption_DoTileDrops: + if (uiVal != 1) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_DOTILEDROPS; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DOTILEDROPS; + } + break; + case eGameHostOption_NaturalRegeneration: + if (uiVal != 1) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_NATURALREGEN; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_NATURALREGEN; + } + break; + case eGameHostOption_DoDaylightCycle: + if (uiVal != 1) { + uiHostSettings |= GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE; + } else { + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE; + } + break; + case eGameHostOption_WorldSize: + uiHostSettings &= ~GAME_HOST_OPTION_BITMASK_WORLDSIZE; + uiHostSettings |= + (GAME_HOST_OPTION_BITMASK_WORLDSIZE & + (uiVal << GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT)); + break; + case eGameHostOption_All: + uiHostSettings = uiVal; + break; + default: + break; + } +} + +unsigned int GameSettingsManager::getGameHostOption( + unsigned int uiHostSettings, eGameHostOption eVal) { + switch (eVal) { + case eGameHostOption_FriendsOfFriends: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_FRIENDSOFFRIENDS); + case eGameHostOption_Difficulty: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_DIFFICULTY); + case eGameHostOption_Gamertags: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_GAMERTAGS); + case eGameHostOption_GameType: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_GAMETYPE) >> 4; + case eGameHostOption_All: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_ALL); + case eGameHostOption_Tutorial: + return ((uiHostSettings & GAME_HOST_OPTION_BITMASK_GAMERTAGS) | + GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS | + GAME_HOST_OPTION_BITMASK_FIRESPREADS | + GAME_HOST_OPTION_BITMASK_TNT | + GAME_HOST_OPTION_BITMASK_PVP | + GAME_HOST_OPTION_BITMASK_STRUCTURES | 1); + case eGameHostOption_LevelType: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_LEVELTYPE); + case eGameHostOption_Structures: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_STRUCTURES); + case eGameHostOption_BonusChest: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_BONUSCHEST); + case eGameHostOption_HasBeenInCreative: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_BEENINCREATIVE); + case eGameHostOption_PvP: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_PVP); + case eGameHostOption_TrustPlayers: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_TRUSTPLAYERS); + case eGameHostOption_TNT: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_TNT); + case eGameHostOption_FireSpreads: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_FIRESPREADS); + case eGameHostOption_CheatsEnabled: + return (uiHostSettings & (GAME_HOST_OPTION_BITMASK_HOSTFLY | + GAME_HOST_OPTION_BITMASK_HOSTHUNGER | + GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE)); + case eGameHostOption_HostCanFly: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_HOSTFLY); + case eGameHostOption_HostCanChangeHunger: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_HOSTHUNGER); + case eGameHostOption_HostCanBeInvisible: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_HOSTINVISIBLE); + case eGameHostOption_BedrockFog: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_BEDROCKFOG); + case eGameHostOption_DisableSaving: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_DISABLESAVE); + case eGameHostOption_WasntSaveOwner: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_NOTOWNER); + case eGameHostOption_WorldSize: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_WORLDSIZE) >> + GAME_HOST_OPTION_BITMASK_WORLDSIZE_BITSHIFT; + case eGameHostOption_MobGriefing: + return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_MOBGRIEFING); + case eGameHostOption_KeepInventory: + return (uiHostSettings & GAME_HOST_OPTION_BITMASK_KEEPINVENTORY); + case eGameHostOption_DoMobSpawning: + return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_DOMOBSPAWNING); + case eGameHostOption_DoMobLoot: + return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_DOMOBLOOT); + case eGameHostOption_DoTileDrops: + return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_DOTILEDROPS); + case eGameHostOption_NaturalRegeneration: + return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_NATURALREGEN); + case eGameHostOption_DoDaylightCycle: + return !(uiHostSettings & GAME_HOST_OPTION_BITMASK_DODAYLIGHTCYCLE); + default: + return 0; + } + return false; +} + +bool GameSettingsManager::canRecordStatsAndAchievements() { + bool isTutorial = Minecraft::GetInstance() != nullptr && + Minecraft::GetInstance()->isTutorial(); + return !(app.GetGameHostOption(eGameHostOption_HasBeenInCreative) || + app.GetGameHostOption(eGameHostOption_HostCanBeInvisible) || + app.GetGameHostOption(eGameHostOption_HostCanChangeHunger) || + app.GetGameHostOption(eGameHostOption_HostCanFly) || + app.GetGameHostOption(eGameHostOption_WasntSaveOwner) || + !app.GetGameHostOption(eGameHostOption_MobGriefing) || + app.GetGameHostOption(eGameHostOption_KeepInventory) || + !app.GetGameHostOption(eGameHostOption_DoMobSpawning) || + (!app.GetGameHostOption(eGameHostOption_DoDaylightCycle) && + !isTutorial)); +} diff --git a/targets/app/common/GameSettingsManager.h b/targets/app/common/GameSettingsManager.h new file mode 100644 index 000000000..4db558432 --- /dev/null +++ b/targets/app/common/GameSettingsManager.h @@ -0,0 +1,77 @@ +#pragma once + +#include + +#include "app/common/App_structs.h" +#include "platform/sdl2/Profile.h" +#include "platform/XboxStubs.h" + +class GameSettingsManager { +public: + GameSettingsManager(); + + void initGameSettings(); + static int oldProfileVersionCallback(void* pParam, unsigned char* pucData, + const unsigned short usVersion, + const int iPad); + static int defaultOptionsCallback(void* pParam, + C_4JProfile::PROFILESETTINGS* pSettings, + const int iPad); + int setDefaultOptions(C_4JProfile::PROFILESETTINGS* pSettings, + const int iPad); + + void setGameSettings(int iPad, eGameSetting eVal, unsigned char ucVal); + unsigned char getGameSettings(int iPad, eGameSetting eVal); + unsigned char getGameSettings(eGameSetting eVal); + + void checkGameSettingsChanged(bool bOverride5MinuteTimer = false, + int iPad = XUSER_INDEX_ANY); + void applyGameSettingsChanged(int iPad); + void clearGameSettingsChangedFlag(int iPad); + void actionGameSettings(int iPad, eGameSetting eVal); + + unsigned int getGameSettingsDebugMask(int iPad = -1, + bool bOverridePlayer = false); + void setGameSettingsDebugMask(int iPad, unsigned int uiVal); + void actionDebugMask(int iPad, bool bSetAllClear = false); + + void setSpecialTutorialCompletionFlag(int iPad, int index); + + // Mash-up pack worlds + void hideMashupPackWorld(int iPad, unsigned int iMashupPackID); + void enableMashupPackWorlds(int iPad); + unsigned int getMashupPackWorlds(int iPad); + + // Language/locale + void setMinecraftLanguage(int iPad, unsigned char ucLanguage); + unsigned char getMinecraftLanguage(int iPad); + void setMinecraftLocale(int iPad, unsigned char ucLocale); + unsigned char getMinecraftLocale(int iPad); + + // Game host options (bitfield versions) + void setGameHostOption(unsigned int& uiHostSettings, eGameHostOption eVal, + unsigned int uiVal); + unsigned int getGameHostOption(unsigned int uiHostSettings, + eGameHostOption eVal); + + bool canRecordStatsAndAchievements(); + + // HandleXuiActions and HandleButtonPresses + void handleXuiActions(); + void handleButtonPresses(); + + // Action-related + static void setActionConfirmed(void* param); + + // Saving message + int displaySavingMessage(const C4JStorage::ESavingMessage eMsg, int iPad); + + // Game settings array - public, referenced by Game via alias + GAME_SETTINGS* GameSettingsA[XUSER_MAX_COUNT]; + + // Game host settings bitfield + unsigned int m_uiGameHostSettings; + +private: + void handleButtonPresses(int iPad); +}; diff --git a/targets/app/common/MenuController.cpp b/targets/app/common/MenuController.cpp new file mode 100644 index 000000000..e9e274b57 --- /dev/null +++ b/targets/app/common/MenuController.cpp @@ -0,0 +1,664 @@ +#include "app/common/MenuController.h" + +#include "app/common/Game.h" +#include "app/common/UI/All Platforms/UIEnums.h" +#include "app/common/UI/All Platforms/UIStructs.h" +#include "app/common/UI/Scenes/UIScene_FullscreenProgress.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/renderer/GameRenderer.h" +#include "minecraft/server/MinecraftServer.h" +#include "minecraft/world/Container.h" +#include "minecraft/world/entity/item/MinecartHopper.h" +#include "minecraft/world/entity/player/Player.h" +#include "minecraft/world/item/crafting/Recipy.h" +#include "minecraft/world/level/tile/Tile.h" +#include "minecraft/world/level/tile/entity/HopperTileEntity.h" +#include "minecraft/world/level/storage/ConsoleSaveFileIO/compression.h" +#include "platform/sdl2/Profile.h" +#include "platform/sdl2/Storage.h" + +#include +#include +#include +#include + +unsigned char MenuController::m_szPNG[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + +MenuController::MenuController() { + for (int i = 0; i < XUSER_MAX_COUNT; i++) { + m_eTMSAction[i] = eTMSAction_Idle; + m_eXuiAction[i] = eAppAction_Idle; + m_eXuiActionParam[i] = nullptr; + m_uiOpacityCountDown[i] = 0; + } + m_eGlobalXuiAction = eAppAction_Idle; + m_eGlobalXuiServerAction = eXuiServerAction_Idle; +} + +void MenuController::setAction(int iPad, eXuiAction action, void* param) { + if ((m_eXuiAction[iPad] == eAppAction_ReloadTexturePack) && + (action == eAppAction_EthernetDisconnected)) { + app.DebugPrintf( + "Invalid change of App action for pad %d from %d to %d, ignoring\n", + iPad, m_eXuiAction[iPad], action); + } else if ((m_eXuiAction[iPad] == eAppAction_ReloadTexturePack) && + (action == eAppAction_ExitWorld)) { + app.DebugPrintf( + "Invalid change of App action for pad %d from %d to %d, ignoring\n", + iPad, m_eXuiAction[iPad], action); + } else if (m_eXuiAction[iPad] == eAppAction_ExitWorldCapturedThumbnail && + action != eAppAction_Idle) { + app.DebugPrintf( + "Invalid change of App action for pad %d from %d to %d, ignoring\n", + iPad, m_eXuiAction[iPad], action); + } else { + app.DebugPrintf("Changing App action for pad %d from %d to %d\n", iPad, + m_eXuiAction[iPad], action); + m_eXuiAction[iPad] = action; + m_eXuiActionParam[iPad] = param; + } +} + +bool MenuController::loadInventoryMenu(int iPad, + std::shared_ptr player, + bool bNavigateBack) { + bool success = true; + + InventoryScreenInput* initData = new InventoryScreenInput(); + initData->player = player; + initData->bNavigateBack = bNavigateBack; + initData->iPad = iPad; + + if (app.GetLocalPlayerCount() > 1) { + initData->bSplitscreen = true; + success = ui.NavigateToScene(iPad, eUIScene_InventoryMenu, initData); + } else { + initData->bSplitscreen = false; + success = ui.NavigateToScene(iPad, eUIScene_InventoryMenu, initData); + } + + return success; +} + +bool MenuController::loadCreativeMenu(int iPad, + std::shared_ptr player, + bool bNavigateBack) { + bool success = true; + + InventoryScreenInput* initData = new InventoryScreenInput(); + initData->player = player; + initData->bNavigateBack = bNavigateBack; + initData->iPad = iPad; + + if (app.GetLocalPlayerCount() > 1) { + initData->bSplitscreen = true; + success = ui.NavigateToScene(iPad, eUIScene_CreativeMenu, initData); + } else { + initData->bSplitscreen = false; + success = ui.NavigateToScene(iPad, eUIScene_CreativeMenu, initData); + } + + return success; +} + +bool MenuController::loadCrafting2x2Menu(int iPad, + std::shared_ptr player) { + bool success = true; + + CraftingPanelScreenInput* initData = new CraftingPanelScreenInput(); + initData->player = player; + initData->iContainerType = RECIPE_TYPE_2x2; + initData->iPad = iPad; + initData->x = 0; + initData->y = 0; + initData->z = 0; + + if (app.GetLocalPlayerCount() > 1) { + initData->bSplitscreen = true; + success = ui.NavigateToScene(iPad, eUIScene_Crafting2x2Menu, initData); + } else { + initData->bSplitscreen = false; + success = ui.NavigateToScene(iPad, eUIScene_Crafting2x2Menu, initData); + } + + return success; +} + +bool MenuController::loadCrafting3x3Menu(int iPad, + std::shared_ptr player, + int x, int y, int z) { + bool success = true; + + CraftingPanelScreenInput* initData = new CraftingPanelScreenInput(); + initData->player = player; + initData->iContainerType = RECIPE_TYPE_3x3; + initData->iPad = iPad; + initData->x = x; + initData->y = y; + initData->z = z; + + if (app.GetLocalPlayerCount() > 1) { + initData->bSplitscreen = true; + success = ui.NavigateToScene(iPad, eUIScene_Crafting3x3Menu, initData); + } else { + initData->bSplitscreen = false; + success = ui.NavigateToScene(iPad, eUIScene_Crafting3x3Menu, initData); + } + + return success; +} + +bool MenuController::loadFireworksMenu(int iPad, + std::shared_ptr player, + int x, int y, int z) { + bool success = true; + + FireworksScreenInput* initData = new FireworksScreenInput(); + initData->player = player; + initData->iPad = iPad; + initData->x = x; + initData->y = y; + initData->z = z; + + if (app.GetLocalPlayerCount() > 1) { + initData->bSplitscreen = true; + success = ui.NavigateToScene(iPad, eUIScene_FireworksMenu, initData); + } else { + initData->bSplitscreen = false; + success = ui.NavigateToScene(iPad, eUIScene_FireworksMenu, initData); + } + + return success; +} + +bool MenuController::loadEnchantingMenu(int iPad, + std::shared_ptr inventory, + int x, int y, int z, Level* level, + const std::wstring& name) { + bool success = true; + + EnchantingScreenInput* initData = new EnchantingScreenInput(); + initData->inventory = inventory; + initData->level = level; + initData->x = x; + initData->y = y; + initData->z = z; + initData->iPad = iPad; + initData->name = name; + + if (app.GetLocalPlayerCount() > 1) { + initData->bSplitscreen = true; + success = ui.NavigateToScene(iPad, eUIScene_EnchantingMenu, initData); + } else { + initData->bSplitscreen = false; + success = ui.NavigateToScene(iPad, eUIScene_EnchantingMenu, initData); + } + + return success; +} + +bool MenuController::loadFurnaceMenu( + int iPad, std::shared_ptr inventory, + std::shared_ptr furnace) { + bool success = true; + + FurnaceScreenInput* initData = new FurnaceScreenInput(); + initData->furnace = furnace; + initData->inventory = inventory; + initData->iPad = iPad; + + if (app.GetLocalPlayerCount() > 1) { + initData->bSplitscreen = true; + success = ui.NavigateToScene(iPad, eUIScene_FurnaceMenu, initData); + } else { + initData->bSplitscreen = false; + success = ui.NavigateToScene(iPad, eUIScene_FurnaceMenu, initData); + } + + return success; +} + +bool MenuController::loadBrewingStandMenu( + int iPad, std::shared_ptr inventory, + std::shared_ptr brewingStand) { + bool success = true; + + BrewingScreenInput* initData = new BrewingScreenInput(); + initData->brewingStand = brewingStand; + initData->inventory = inventory; + initData->iPad = iPad; + + if (app.GetLocalPlayerCount() > 1) { + initData->bSplitscreen = true; + success = ui.NavigateToScene(iPad, eUIScene_BrewingStandMenu, initData); + } else { + initData->bSplitscreen = false; + success = ui.NavigateToScene(iPad, eUIScene_BrewingStandMenu, initData); + } + + return success; +} + +bool MenuController::loadContainerMenu(int iPad, + std::shared_ptr inventory, + std::shared_ptr container) { + bool success = true; + + ContainerScreenInput* initData = new ContainerScreenInput(); + initData->inventory = inventory; + initData->container = container; + initData->iPad = iPad; + + if (app.GetLocalPlayerCount() > 1) { + initData->bSplitscreen = true; + + bool bLargeChest = + (initData->container->getContainerSize() > 3 * 9) ? true : false; + if (bLargeChest) { + success = + ui.NavigateToScene(iPad, eUIScene_LargeContainerMenu, initData); + } else { + success = + ui.NavigateToScene(iPad, eUIScene_ContainerMenu, initData); + } + } else { + initData->bSplitscreen = false; + success = ui.NavigateToScene(iPad, eUIScene_ContainerMenu, initData); + } + + return success; +} + +bool MenuController::loadTrapMenu( + int iPad, std::shared_ptr inventory, + std::shared_ptr trap) { + bool success = true; + + TrapScreenInput* initData = new TrapScreenInput(); + initData->inventory = inventory; + initData->trap = trap; + initData->iPad = iPad; + + if (app.GetLocalPlayerCount() > 1) { + initData->bSplitscreen = true; + success = ui.NavigateToScene(iPad, eUIScene_DispenserMenu, initData); + } else { + initData->bSplitscreen = false; + success = ui.NavigateToScene(iPad, eUIScene_DispenserMenu, initData); + } + + return success; +} + +bool MenuController::loadSignEntryMenu( + int iPad, std::shared_ptr sign) { + bool success = true; + + SignEntryScreenInput* initData = new SignEntryScreenInput(); + initData->sign = sign; + initData->iPad = iPad; + + success = ui.NavigateToScene(iPad, eUIScene_SignEntryMenu, initData); + + delete initData; + + return success; +} + +bool MenuController::loadRepairingMenu(int iPad, + std::shared_ptr inventory, + Level* level, int x, int y, int z) { + bool success = true; + + AnvilScreenInput* initData = new AnvilScreenInput(); + initData->inventory = inventory; + initData->level = level; + initData->x = x; + initData->y = y; + initData->z = z; + initData->iPad = iPad; + if (app.GetLocalPlayerCount() > 1) + initData->bSplitscreen = true; + else + initData->bSplitscreen = false; + + success = ui.NavigateToScene(iPad, eUIScene_AnvilMenu, initData); + + return success; +} + +bool MenuController::loadTradingMenu(int iPad, + std::shared_ptr inventory, + std::shared_ptr trader, + Level* level, const std::wstring& name) { + bool success = true; + + TradingScreenInput* initData = new TradingScreenInput(); + initData->inventory = inventory; + initData->trader = trader; + initData->level = level; + initData->iPad = iPad; + if (app.GetLocalPlayerCount() > 1) + initData->bSplitscreen = true; + else + initData->bSplitscreen = false; + + success = ui.NavigateToScene(iPad, eUIScene_TradingMenu, initData); + + return success; +} + +bool MenuController::loadHopperMenu( + int iPad, std::shared_ptr inventory, + std::shared_ptr hopper) { + bool success = true; + + HopperScreenInput* initData = new HopperScreenInput(); + initData->inventory = inventory; + initData->hopper = hopper; + initData->iPad = iPad; + if (app.GetLocalPlayerCount() > 1) + initData->bSplitscreen = true; + else + initData->bSplitscreen = false; + + success = ui.NavigateToScene(iPad, eUIScene_HopperMenu, initData); + + return success; +} + +bool MenuController::loadHopperMenu( + int iPad, std::shared_ptr inventory, + std::shared_ptr hopper) { + bool success = true; + + HopperScreenInput* initData = new HopperScreenInput(); + initData->inventory = inventory; + initData->hopper = std::dynamic_pointer_cast(hopper); + initData->iPad = iPad; + if (app.GetLocalPlayerCount() > 1) + initData->bSplitscreen = true; + else + initData->bSplitscreen = false; + + success = ui.NavigateToScene(iPad, eUIScene_HopperMenu, initData); + + return success; +} + +bool MenuController::loadHorseMenu(int iPad, + std::shared_ptr inventory, + std::shared_ptr container, + std::shared_ptr horse) { + bool success = true; + + HorseScreenInput* initData = new HorseScreenInput(); + initData->inventory = inventory; + initData->container = container; + initData->horse = horse; + initData->iPad = iPad; + if (app.GetLocalPlayerCount() > 1) + initData->bSplitscreen = true; + else + initData->bSplitscreen = false; + + success = ui.NavigateToScene(iPad, eUIScene_HorseMenu, initData); + + return success; +} + +bool MenuController::loadBeaconMenu( + int iPad, std::shared_ptr inventory, + std::shared_ptr beacon) { + bool success = true; + + BeaconScreenInput* initData = new BeaconScreenInput(); + initData->inventory = inventory; + initData->beacon = beacon; + initData->iPad = iPad; + if (app.GetLocalPlayerCount() > 1) + initData->bSplitscreen = true; + else + initData->bSplitscreen = false; + + success = ui.NavigateToScene(iPad, eUIScene_BeaconMenu, initData); + + return success; +} + +int MenuController::texturePackDialogReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result) { + return 0; +} + +int MenuController::unlockFullInviteReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result) { + Minecraft* pMinecraft = Minecraft::GetInstance(); + bool bNoPlayer; + + if (pMinecraft->player == nullptr) { + bNoPlayer = true; + } + + return 0; +} + +int MenuController::unlockFullSaveReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result) { + return 0; +} + +int MenuController::unlockFullExitReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result) { + Game* pApp = (Game*)pParam; + Minecraft* pMinecraft = Minecraft::GetInstance(); + + if (result != C4JStorage::EMessage_ResultAccept) { + pApp->SetAction(pMinecraft->player->GetXboxPad(), + eAppAction_ExitWorldTrial); + } + + return 0; +} + +int MenuController::trialOverReturned(void* pParam, int iPad, + C4JStorage::EMessageResult result) { + Game* pApp = (Game*)pParam; + Minecraft* pMinecraft = Minecraft::GetInstance(); + + if (result != C4JStorage::EMessage_ResultAccept) { + pApp->SetAction(pMinecraft->player->GetXboxPad(), eAppAction_ExitTrial); + } + + return 0; +} + +int MenuController::remoteSaveThreadProc(void* lpParameter) { + Compression::UseDefaultThreadStorage(); + Tile::CreateNewThreadStorage(); + + Minecraft* pMinecraft = Minecraft::GetInstance(); + + pMinecraft->progressRenderer->progressStartNoAbort( + IDS_PROGRESS_HOST_SAVING); + pMinecraft->progressRenderer->progressStage(-1); + pMinecraft->progressRenderer->progressStagePercentage(0); + + while (!app.GetGameStarted() && + app.GetXuiAction(ProfileManager.GetPrimaryPad()) == + eAppAction_WaitRemoteServerSaveComplete) { + pMinecraft->tickAllConnections(); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + if (app.GetXuiAction(ProfileManager.GetPrimaryPad()) != + eAppAction_WaitRemoteServerSaveComplete) { + return ERROR_CANCELLED; + } + app.SetAction(ProfileManager.GetPrimaryPad(), eAppAction_Idle); + + ui.UpdatePlayerBasePositions(); + + Tile::ReleaseThreadStorage(); + + return 0; +} + +void MenuController::exitGameFromRemoteSave(void* lpParameter) { + int primaryPad = ProfileManager.GetPrimaryPad(); + + unsigned int uiIDA[3]; + uiIDA[0] = IDS_CONFIRM_CANCEL; + uiIDA[1] = IDS_CONFIRM_OK; + + ui.RequestAlertMessage( + IDS_EXIT_GAME, IDS_CONFIRM_EXIT_GAME, uiIDA, 2, primaryPad, + &MenuController::exitGameFromRemoteSaveDialogReturned, nullptr); +} + +int MenuController::exitGameFromRemoteSaveDialogReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result) { + if (result == C4JStorage::EMessage_ResultDecline) { + app.SetAction(iPad, eAppAction_ExitWorld); + } else { + UIScene_FullscreenProgress* pScene = + (UIScene_FullscreenProgress*)ui.FindScene( + eUIScene_FullscreenProgress); + if (pScene != nullptr) { + pScene->SetWasCancelled(false); + } + } + return 0; +} + +#define PNG_TAG_tEXt 0x74455874 + +unsigned int MenuController::fromBigEndian(unsigned int uiValue) { + unsigned int uiReturn = + ((uiValue >> 24) & 0x000000ff) | ((uiValue >> 8) & 0x0000ff00) | + ((uiValue << 8) & 0x00ff0000) | ((uiValue << 24) & 0xff000000); + return uiReturn; +} + +void MenuController::getImageTextData(std::uint8_t* imageData, + unsigned int imageBytes, + unsigned char* seedText, + unsigned int& uiHostOptions, + bool& bHostOptionsRead, + std::uint32_t& uiTexturePack) { + auto readPngUInt32 = [](const std::uint8_t* data) -> unsigned int { + unsigned int value = 0; + std::memcpy(&value, data, sizeof(value)); + return value; + }; + + std::uint8_t* ucPtr = imageData; + unsigned int uiCount = 0; + unsigned int uiChunkLen; + unsigned int uiChunkType; + unsigned int uiCRC; + char szKeyword[80]; + + for (int i = 0; i < 8; i++) { + if (m_szPNG[i] != ucPtr[i]) return; + } + + uiCount += 8; + + while (uiCount < imageBytes) { + uiChunkLen = fromBigEndian(readPngUInt32(&ucPtr[uiCount])); + uiCount += sizeof(int); + uiChunkType = fromBigEndian(readPngUInt32(&ucPtr[uiCount])); + uiCount += sizeof(int); + + if (uiChunkType == PNG_TAG_tEXt) { + unsigned char* pszKeyword = &ucPtr[uiCount]; + while (pszKeyword < ucPtr + uiCount + uiChunkLen) { + memset(szKeyword, 0, 80); + unsigned int uiKeywordC = 0; + while (*pszKeyword != 0) { + szKeyword[uiKeywordC++] = *pszKeyword; + pszKeyword++; + } + pszKeyword++; + if (strcmp(szKeyword, "4J_SEED") == 0) { + unsigned int uiValueC = 0; + while (*pszKeyword != 0 && + (pszKeyword < ucPtr + uiCount + uiChunkLen)) { + seedText[uiValueC++] = *pszKeyword; + pszKeyword++; + } + } else if (strcmp(szKeyword, "4J_HOSTOPTIONS") == 0) { + bHostOptionsRead = true; + unsigned int uiValueC = 0; + unsigned char pszHostOptions[9]; + memset(&pszHostOptions, 0, 9); + while (*pszKeyword != 0 && + (pszKeyword < ucPtr + uiCount + uiChunkLen) && + uiValueC < 8) { + pszHostOptions[uiValueC++] = *pszKeyword; + pszKeyword++; + } + + uiHostOptions = 0; + std::stringstream ss; + ss << pszHostOptions; + ss >> std::hex >> uiHostOptions; + } else if (strcmp(szKeyword, "4J_TEXTUREPACK") == 0) { + unsigned int uiValueC = 0; + unsigned char pszTexturePack[9]; + memset(&pszTexturePack, 0, 9); + while (*pszKeyword != 0 && + (pszKeyword < ucPtr + uiCount + uiChunkLen) && + uiValueC < 8) { + pszTexturePack[uiValueC++] = *pszKeyword; + pszKeyword++; + } + + std::stringstream ss; + ss << pszTexturePack; + ss >> std::hex >> uiTexturePack; + } + } + } + uiCount += uiChunkLen; + uiCRC = fromBigEndian(readPngUInt32(&ucPtr[uiCount])); + uiCount += sizeof(int); + } + + return; +} + +unsigned int MenuController::createImageTextData( + std::uint8_t* textMetadata, int64_t seed, bool hasSeed, + unsigned int uiHostOptions, unsigned int uiTexturePackId) { + int iTextMetadataBytes = 0; + if (hasSeed) { + strcpy((char*)textMetadata, "4J_SEED"); + snprintf((char*)&textMetadata[8], 42, "%lld", (long long)seed); + + iTextMetadataBytes += 8; + while (textMetadata[iTextMetadataBytes] != 0) iTextMetadataBytes++; + ++iTextMetadataBytes; + } + + strcpy((char*)&textMetadata[iTextMetadataBytes], "4J_HOSTOPTIONS"); + snprintf((char*)&textMetadata[iTextMetadataBytes + 15], 9, "%X", + uiHostOptions); + + iTextMetadataBytes += 15; + while (textMetadata[iTextMetadataBytes] != 0) iTextMetadataBytes++; + ++iTextMetadataBytes; + + strcpy((char*)&textMetadata[iTextMetadataBytes], "4J_TEXTUREPACK"); + snprintf((char*)&textMetadata[iTextMetadataBytes + 15], 9, "%X", + uiHostOptions); + + iTextMetadataBytes += 15; + while (textMetadata[iTextMetadataBytes] != 0) iTextMetadataBytes++; + + return iTextMetadataBytes; +} diff --git a/targets/app/common/MenuController.h b/targets/app/common/MenuController.h new file mode 100644 index 000000000..c373df31e --- /dev/null +++ b/targets/app/common/MenuController.h @@ -0,0 +1,151 @@ +#pragma once + +#include +#include +#include + +#include "app/common/App_structs.h" +#include "platform/sdl2/Storage.h" +#include "platform/XboxStubs.h" + +class Player; +class Inventory; +class Level; +class FurnaceTileEntity; +class Container; +class DispenserTileEntity; +class SignTileEntity; +class BrewingStandTileEntity; +class HopperTileEntity; +class MinecartHopper; +class EntityHorse; +class BeaconTileEntity; +class LocalPlayer; +class Merchant; +class CommandBlockEntity; + +class MenuController { +public: + MenuController(); + + // Load menu methods + bool loadInventoryMenu(int iPad, std::shared_ptr player, + bool bNavigateBack = false); + bool loadCreativeMenu(int iPad, std::shared_ptr player, + bool bNavigateBack = false); + bool loadEnchantingMenu(int iPad, std::shared_ptr inventory, + int x, int y, int z, Level* level, + const std::wstring& name); + bool loadFurnaceMenu(int iPad, std::shared_ptr inventory, + std::shared_ptr furnace); + bool loadBrewingStandMenu( + int iPad, std::shared_ptr inventory, + std::shared_ptr brewingStand); + bool loadContainerMenu(int iPad, std::shared_ptr inventory, + std::shared_ptr container); + bool loadTrapMenu(int iPad, std::shared_ptr inventory, + std::shared_ptr trap); + bool loadCrafting2x2Menu(int iPad, std::shared_ptr player); + bool loadCrafting3x3Menu(int iPad, std::shared_ptr player, + int x, int y, int z); + bool loadFireworksMenu(int iPad, std::shared_ptr player, + int x, int y, int z); + bool loadSignEntryMenu(int iPad, std::shared_ptr sign); + bool loadRepairingMenu(int iPad, std::shared_ptr inventory, + Level* level, int x, int y, int z); + bool loadTradingMenu(int iPad, std::shared_ptr inventory, + std::shared_ptr trader, Level* level, + const std::wstring& name); + bool loadHopperMenu(int iPad, std::shared_ptr inventory, + std::shared_ptr hopper); + bool loadHopperMenu(int iPad, std::shared_ptr inventory, + std::shared_ptr hopper); + bool loadHorseMenu(int iPad, std::shared_ptr inventory, + std::shared_ptr container, + std::shared_ptr horse); + bool loadBeaconMenu(int iPad, std::shared_ptr inventory, + std::shared_ptr beacon); + + // Action management + void setAction(int iPad, eXuiAction action, void* param = nullptr); + eXuiAction getXuiAction(int iPad) { return m_eXuiAction[iPad]; } + void setXuiServerAction(int iPad, eXuiServerAction action, + void* param = nullptr) { + m_eXuiServerAction[iPad] = action; + m_eXuiServerActionParam[iPad] = param; + } + eXuiServerAction getXuiServerAction(int iPad) { + return m_eXuiServerAction[iPad]; + } + void* getXuiServerActionParam(int iPad) { + return m_eXuiServerActionParam[iPad]; + } + eXuiAction getGlobalXuiAction() { return m_eGlobalXuiAction; } + void setGlobalXuiAction(eXuiAction action) { m_eGlobalXuiAction = action; } + eXuiServerAction getGlobalXuiServerAction() { + return m_eGlobalXuiServerAction; + } + void setGlobalXuiServerAction(eXuiServerAction action) { + m_eGlobalXuiServerAction = action; + } + + // TMS action + void setTMSAction(int iPad, eTMSAction action) { + m_eTMSAction[iPad] = action; + } + eTMSAction getTMSAction(int iPad) { return m_eTMSAction[iPad]; } + + // Dialog callbacks + static int texturePackDialogReturned(void* pParam, int iPad, + C4JStorage::EMessageResult result); + static int fatalErrorDialogReturned(void* pParam, int iPad, + C4JStorage::EMessageResult result); + static int trialOverReturned(void* pParam, int iPad, + C4JStorage::EMessageResult result); + static int unlockFullExitReturned(void* pParam, int iPad, + C4JStorage::EMessageResult result); + static int unlockFullSaveReturned(void* pParam, int iPad, + C4JStorage::EMessageResult result); + static int unlockFullInviteReturned(void* pParam, int iPad, + C4JStorage::EMessageResult result); + + // Remote save + static int remoteSaveThreadProc(void* lpParameter); + static void exitGameFromRemoteSave(void* lpParameter); + static int exitGameFromRemoteSaveDialogReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result); + + // Image text data + void getImageTextData(std::uint8_t* imageData, unsigned int imageBytes, + unsigned char* seedText, unsigned int& uiHostOptions, + bool& bHostOptionsRead, std::uint32_t& uiTexturePack); + unsigned int createImageTextData(std::uint8_t* textMetadata, int64_t seed, + bool hasSeed, unsigned int uiHostOptions, + unsigned int uiTexturePackId); + + // Opacity timer + unsigned int getOpacityTimer(int iPad) { + return m_uiOpacityCountDown[iPad]; + } + void setOpacityTimer(int iPad) { m_uiOpacityCountDown[iPad] = 120; } + void tickOpacityTimer(int iPad) { + if (m_uiOpacityCountDown[iPad] > 0) m_uiOpacityCountDown[iPad]--; + } + + // Action param accessor (needed by HandleXuiActions) + void* getXuiActionParam(int iPad) { return m_eXuiActionParam[iPad]; } + +private: + eXuiAction m_eXuiAction[XUSER_MAX_COUNT]; + eTMSAction m_eTMSAction[XUSER_MAX_COUNT]; + void* m_eXuiActionParam[XUSER_MAX_COUNT]; + eXuiAction m_eGlobalXuiAction; + eXuiServerAction m_eXuiServerAction[XUSER_MAX_COUNT]; + void* m_eXuiServerActionParam[XUSER_MAX_COUNT]; + eXuiServerAction m_eGlobalXuiServerAction; + + unsigned int m_uiOpacityCountDown[XUSER_MAX_COUNT]; + + static unsigned char m_szPNG[8]; + unsigned int fromBigEndian(unsigned int uiValue); +}; diff --git a/targets/app/common/NetworkController.cpp b/targets/app/common/NetworkController.cpp new file mode 100644 index 000000000..d66ff0057 --- /dev/null +++ b/targets/app/common/NetworkController.cpp @@ -0,0 +1,518 @@ +#include "app/common/NetworkController.h" + +#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/stats/StatsCounter.h" +#include "minecraft/world/entity/player/Player.h" +#include "minecraft/world/level/tile/Tile.h" +#include "minecraft/world/level/storage/ConsoleSaveFileIO/compression.h" +#include "platform/sdl2/Input.h" +#include "platform/sdl2/Profile.h" +#include "platform/sdl2/Storage.h" +#include "app/common/Audio/SoundEngine.h" + +#include +#include +#include + +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 (FAILED(XUserGetSigninInfo(i, + XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY, + &m_currentSigninInfo[i]))) { + 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 C4JStorage::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 C4JStorage::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 = ProfileManager.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 = ProfileManager.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 = ProfileManager.GetPrimaryPad(); + + if ((ProfileManager.GetLockedProfile() != -1) && iPrimaryPlayer != -1) { + if (((uiSignInData & (1 << iPrimaryPlayer)) == 0) || + bPrimaryPlayerChanged) { + pApp->SetAction(iPrimaryPlayer, eAppAction_PrimaryPlayerSignedOut); + pApp->InvalidateBannedList(iPrimaryPlayer); + StorageManager.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 (ProfileManager.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, ProfileManager.GetPrimaryPad()); + } + + bool switchToOffline = false; + if (!ProfileManager.IsSignedInLive( + ProfileManager.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 && + !ProfileManager.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() && + !ProfileManager.IsSignedInLive( + ProfileManager.GetLockedProfile())) { + { + pApp->SetAction(iPrimaryPlayer, + eAppAction_EthernetDisconnected); + } + } + } + m_uiLastSignInData = uiSignInData; + } else if (iPrimaryPlayer != -1) { + pApp->InvalidateBannedList(iPrimaryPlayer); + StorageManager.ClearDLCOffers(); + pApp->ClearAndResetDLCDownloadQueue(); + pApp->ClearDLCInstalled(); + } + + for (unsigned int i = 0; i < XUSER_MAX_COUNT; ++i) { + if (FAILED(XUserGetSigninInfo( + i, XUSER_GET_SIGNIN_INFO_OFFLINE_XUID_ONLY, + &pApp->m_networkController.m_currentSigninInfo[i]))) { + 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 (!InputManager.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(ProfileManager.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, C4JStorage::EMessageResult result) { + Game* pApp = (Game*)pParam; + + if (result == C4JStorage::EMessage_ResultDecline) { + pApp->SetAction(iPad, eAppAction_ExitAndJoinFromInviteConfirmed); + } + + return 0; +} + +int NetworkController::exitAndJoinFromInviteSaveDialogReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result) { + Game* pClass = (Game*)pParam; + if (result == C4JStorage::EMessage_ResultDecline || + result == C4JStorage::EMessage_ResultThirdOption) { + if (result == C4JStorage::EMessage_ResultDecline) { + if (!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) { + TexturePack* tPack = + Minecraft::GetInstance()->skins->getSelected(); + DLCPack* pDLCPack = tPack->getDLCPack(); + if (!pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Texture, + L"")) { + 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; + StorageManager.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, + ProfileManager.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, ProfileManager.GetPrimaryPad(), + &NetworkController::exitAndJoinFromInviteDeclineSaveReturned, + pClass); + return 0; + } + + app.SetAction(ProfileManager.GetPrimaryPad(), + eAppAction_ExitAndJoinFromInviteConfirmed); + } + return 0; +} + +int NetworkController::warningTrialTexturePackReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result) { + return 0; +} + +int NetworkController::exitAndJoinFromInviteAndSaveReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result) { + if (result == C4JStorage::EMessage_ResultDecline) { + if (!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) { + TexturePack* tPack = Minecraft::GetInstance()->skins->getSelected(); + DLCPack* pDLCPack = tPack->getDLCPack(); + if (!pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Texture, + L"")) { + 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, C4JStorage::EMessageResult result) { + if (result == C4JStorage::EMessage_ResultDecline) { + MinecraftServer::getInstance()->setSaveOnExit(false); + app.SetAction(iPad, eAppAction_ExitAndJoinFromInviteConfirmed); + } + return 0; +} diff --git a/targets/app/common/NetworkController.h b/targets/app/common/NetworkController.h new file mode 100644 index 000000000..7df2ddb0e --- /dev/null +++ b/targets/app/common/NetworkController.h @@ -0,0 +1,106 @@ +#pragma once + +#include + +#include "app/common/App_structs.h" +#include "platform/NetTypes.h" +#include "platform/sdl2/Storage.h" +#include "platform/XboxStubs.h" +#include "protocol/DisconnectPacket.h" + +struct INVITE_INFO; + +typedef struct _JoinFromInviteData { + std::uint32_t dwUserIndex; + std::uint32_t dwLocalUsersMask; + const INVITE_INFO* pInviteInfo; +} JoinFromInviteData; + +class NetworkController { +public: + NetworkController(); + + // Player info + void updatePlayerInfo(std::uint8_t networkSmallId, + int16_t playerColourIndex, + unsigned int playerGamePrivileges); + short getPlayerColour(std::uint8_t networkSmallId); + unsigned int getPlayerPrivileges(std::uint8_t networkSmallId); + + // Sign-in change + static void signInChangeCallback(void* pParam, bool bVal, + unsigned int uiSignInData); + static void clearSignInChangeUsersMask(); + static int signoutExitWorldThreadProc(void* lpParameter); + static int primaryPlayerSignedOutReturned(void* pParam, int iPad, + const C4JStorage::EMessageResult); + static int ethernetDisconnectReturned(void* pParam, int iPad, + const C4JStorage::EMessageResult); + static void profileReadErrorCallback(void* pParam); + + // Notifications + static void notificationsCallback(void* pParam, + std::uint32_t dwNotification, + unsigned int uiParam); + + // Ethernet/Live link + static void liveLinkChangeCallback(void* pParam, bool bConnected); + + // Invites + void processInvite(std::uint32_t dwUserIndex, + std::uint32_t dwLocalUsersMask, + const INVITE_INFO* pInviteInfo); + static int exitAndJoinFromInvite(void* pParam, int iPad, + C4JStorage::EMessageResult result); + static int exitAndJoinFromInviteSaveDialogReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result); + static int exitAndJoinFromInviteAndSaveReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result); + static int exitAndJoinFromInviteDeclineSaveReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result); + static int warningTrialTexturePackReturned( + void* pParam, int iPad, C4JStorage::EMessageResult result); + + // Disconnect + DisconnectPacket::eDisconnectReason getDisconnectReason() { + return m_disconnectReason; + } + void setDisconnectReason(DisconnectPacket::eDisconnectReason bVal) { + m_disconnectReason = bVal; + } + + // Session type flags + bool getChangingSessionType() { return m_bChangingSessionType; } + void setChangingSessionType(bool bVal) { m_bChangingSessionType = bVal; } + bool getReallyChangingSessionType() { return m_bReallyChangingSessionType; } + void setReallyChangingSessionType(bool bVal) { + m_bReallyChangingSessionType = bVal; + } + + // Live link + bool getLiveLinkRequired() { return m_bLiveLinkRequired; } + void setLiveLinkRequired(bool required) { m_bLiveLinkRequired = required; } + + // Sign-in info + XUSER_SIGNIN_INFO m_currentSigninInfo[XUSER_MAX_COUNT]; + + // Invite data + JoinFromInviteData m_InviteData; + + // Notifications + typedef std::vector VNOTIFICATIONS; + VNOTIFICATIONS m_vNotifications; + VNOTIFICATIONS* getNotifications() { return &m_vNotifications; } + + // Static sign-in data + static unsigned int m_uiLastSignInData; + +private: + std::uint8_t m_playerColours[MINECRAFT_NET_MAX_PLAYERS]; + unsigned int m_playerGamePrivileges[MINECRAFT_NET_MAX_PLAYERS]; + + DisconnectPacket::eDisconnectReason m_disconnectReason; + bool m_bChangingSessionType; + bool m_bReallyChangingSessionType; + bool m_bLiveLinkRequired; +}; diff --git a/targets/app/common/UI/All Platforms/UIStructs.h b/targets/app/common/UI/All Platforms/UIStructs.h index 86561267d..f164eb8ab 100644 --- a/targets/app/common/UI/All Platforms/UIStructs.h +++ b/targets/app/common/UI/All Platforms/UIStructs.h @@ -382,13 +382,13 @@ typedef struct _SignInInfo { } SignInInfo; // Credits -typedef struct { +struct SCreditTextItemDef { const wchar_t* m_Text; // Should contain string, optionally with %s to add // in translated string ... e.g. "Andy West - %s" int m_iStringID[2]; // May be NO_TRANSLATED_STRING if we do not require to // add any translated string. ECreditTextTypes m_eType; -} SCreditTextItemDef; +}; // Message box typedef struct _MessageBoxInfo {