Merge pull request #201 from dtentiion/pr/win64-world-saves
Show actual world names in save list, sorting, preserve level and its name on load/resave
This commit is contained in:
@@ -1085,6 +1085,7 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD
|
|||||||
__int64 seedValue = 0;
|
__int64 seedValue = 0;
|
||||||
|
|
||||||
NetworkGameInitData *param = new NetworkGameInitData();
|
NetworkGameInitData *param = new NetworkGameInitData();
|
||||||
|
param->levelName = wWorldName;
|
||||||
|
|
||||||
if (wSeed.length() != 0)
|
if (wSeed.length() != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -246,6 +246,16 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye
|
|||||||
mbstowcs(wSaveName, params->saveDetails->UTF8SaveName, strlen(params->saveDetails->UTF8SaveName)+1); // plus null
|
mbstowcs(wSaveName, params->saveDetails->UTF8SaveName, strlen(params->saveDetails->UTF8SaveName)+1); // plus null
|
||||||
m_labelGameName.init(wSaveName);
|
m_labelGameName.init(wSaveName);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
if (params->saveDetails != NULL && params->saveDetails->UTF8SaveName[0] != '\0')
|
||||||
|
{
|
||||||
|
wchar_t wSaveName[128];
|
||||||
|
ZeroMemory(wSaveName, sizeof(wSaveName));
|
||||||
|
mbstowcs(wSaveName, params->saveDetails->UTF8SaveName, 127);
|
||||||
|
m_levelName = wstring(wSaveName);
|
||||||
|
m_labelGameName.init(m_levelName);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1574,6 +1584,7 @@ void UIScene_LoadMenu::StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocal
|
|||||||
param->saveData = NULL;
|
param->saveData = NULL;
|
||||||
param->levelGen = pClass->m_levelGen;
|
param->levelGen = pClass->m_levelGen;
|
||||||
param->texturePackId = pClass->m_MoreOptionsParams.dwTexturePack;
|
param->texturePackId = pClass->m_MoreOptionsParams.dwTexturePack;
|
||||||
|
param->levelName = pClass->m_levelName;
|
||||||
|
|
||||||
Minecraft *pMinecraft = Minecraft::GetInstance();
|
Minecraft *pMinecraft = Minecraft::GetInstance();
|
||||||
pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack);
|
pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack);
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ private:
|
|||||||
bool m_bIsCorrupt;
|
bool m_bIsCorrupt;
|
||||||
bool m_bThumbnailGetFailed;
|
bool m_bThumbnailGetFailed;
|
||||||
__int64 m_seed;
|
__int64 m_seed;
|
||||||
|
wstring m_levelName;
|
||||||
|
|
||||||
#ifdef __PS3__
|
#ifdef __PS3__
|
||||||
std::vector<SonyCommerce::ProductInfo>*m_pvProductInfo;
|
std::vector<SonyCommerce::ProductInfo>*m_pvProductInfo;
|
||||||
|
|||||||
@@ -25,6 +25,98 @@
|
|||||||
#include "message_dialog.h"
|
#include "message_dialog.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
#include "..\..\..\Minecraft.World\NbtIo.h"
|
||||||
|
#include "..\..\..\Minecraft.World\compression.h"
|
||||||
|
|
||||||
|
static wstring ReadLevelNameFromSaveFile(const wstring& filePath)
|
||||||
|
{
|
||||||
|
HANDLE hFile = CreateFileW(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE) return L"";
|
||||||
|
|
||||||
|
DWORD fileSize = GetFileSize(hFile, NULL);
|
||||||
|
if (fileSize < 12 || fileSize == INVALID_FILE_SIZE) { CloseHandle(hFile); return L""; }
|
||||||
|
|
||||||
|
unsigned char *rawData = new unsigned char[fileSize];
|
||||||
|
DWORD bytesRead = 0;
|
||||||
|
if (!ReadFile(hFile, rawData, fileSize, &bytesRead, NULL) || bytesRead != fileSize)
|
||||||
|
{
|
||||||
|
CloseHandle(hFile);
|
||||||
|
delete[] rawData;
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
CloseHandle(hFile);
|
||||||
|
|
||||||
|
unsigned char *saveData = NULL;
|
||||||
|
unsigned int saveSize = 0;
|
||||||
|
bool freeSaveData = false;
|
||||||
|
|
||||||
|
if (*(unsigned int*)rawData == 0)
|
||||||
|
{
|
||||||
|
// Compressed format: bytes 0-3=0, bytes 4-7=decompressed size, bytes 8+=compressed data
|
||||||
|
unsigned int decompSize = *(unsigned int*)(rawData + 4);
|
||||||
|
if (decompSize == 0 || decompSize > 128 * 1024 * 1024)
|
||||||
|
{
|
||||||
|
delete[] rawData;
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
saveData = new unsigned char[decompSize];
|
||||||
|
Compression::getCompression()->Decompress(saveData, &decompSize, rawData + 8, fileSize - 8);
|
||||||
|
saveSize = decompSize;
|
||||||
|
freeSaveData = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
saveData = rawData;
|
||||||
|
saveSize = fileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
wstring result = L"";
|
||||||
|
if (saveSize >= 12)
|
||||||
|
{
|
||||||
|
unsigned int headerOffset = *(unsigned int*)saveData;
|
||||||
|
unsigned int numEntries = *(unsigned int*)(saveData + 4);
|
||||||
|
const unsigned int entrySize = sizeof(FileEntrySaveData);
|
||||||
|
|
||||||
|
if (headerOffset < saveSize && numEntries > 0 && numEntries < 10000 &&
|
||||||
|
headerOffset + numEntries * entrySize <= saveSize)
|
||||||
|
{
|
||||||
|
FileEntrySaveData *table = (FileEntrySaveData *)(saveData + headerOffset);
|
||||||
|
for (unsigned int i = 0; i < numEntries; i++)
|
||||||
|
{
|
||||||
|
if (wcscmp(table[i].filename, L"level.dat") == 0)
|
||||||
|
{
|
||||||
|
unsigned int off = table[i].startOffset;
|
||||||
|
unsigned int len = table[i].length;
|
||||||
|
if (off >= 12 && off + len <= saveSize && len > 0 && len < 4 * 1024 * 1024)
|
||||||
|
{
|
||||||
|
byteArray ba;
|
||||||
|
ba.data = (byte*)(saveData + off);
|
||||||
|
ba.length = len;
|
||||||
|
CompoundTag *root = NbtIo::decompress(ba);
|
||||||
|
if (root != NULL)
|
||||||
|
{
|
||||||
|
CompoundTag *dataTag = root->getCompound(L"Data");
|
||||||
|
if (dataTag != NULL)
|
||||||
|
result = dataTag->getString(L"LevelName");
|
||||||
|
delete root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (freeSaveData) delete[] saveData;
|
||||||
|
delete[] rawData;
|
||||||
|
// "world" is the engine default — it means no real name was ever set, so
|
||||||
|
// return empty to let the caller fall back to the save filename (timestamp).
|
||||||
|
if (result == L"world") result = L"";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef SONY_REMOTE_STORAGE_DOWNLOAD
|
#ifdef SONY_REMOTE_STORAGE_DOWNLOAD
|
||||||
unsigned long UIScene_LoadOrJoinMenu::m_ulFileSize=0L;
|
unsigned long UIScene_LoadOrJoinMenu::m_ulFileSize=0L;
|
||||||
@@ -159,7 +251,7 @@ UIScene_LoadOrJoinMenu::UIScene_LoadOrJoinMenu(int iPad, void *initData, UILayer
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) || defined(_DURANGO)
|
#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) || defined(_DURANGO) || defined(_WINDOWS64)
|
||||||
// Always clear the saves when we enter this menu
|
// Always clear the saves when we enter this menu
|
||||||
StorageManager.ClearSavesInfo();
|
StorageManager.ClearSavesInfo();
|
||||||
#endif
|
#endif
|
||||||
@@ -614,6 +706,22 @@ void UIScene_LoadOrJoinMenu::tick()
|
|||||||
m_saveDetails = new SaveListDetails[m_pSaveDetails->iSaveC];
|
m_saveDetails = new SaveListDetails[m_pSaveDetails->iSaveC];
|
||||||
|
|
||||||
m_iSaveDetailsCount = m_pSaveDetails->iSaveC;
|
m_iSaveDetailsCount = m_pSaveDetails->iSaveC;
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
// Build sorted index array (newest-first by filename timestamp YYYYMMDDHHMMSS)
|
||||||
|
int *sortedIdx = new int[m_pSaveDetails->iSaveC];
|
||||||
|
for (int si = 0; si < (int)m_pSaveDetails->iSaveC; ++si) sortedIdx[si] = si;
|
||||||
|
for (int si = 1; si < (int)m_pSaveDetails->iSaveC; ++si)
|
||||||
|
{
|
||||||
|
int key = sortedIdx[si];
|
||||||
|
int sj = si - 1;
|
||||||
|
while (sj >= 0 && strcmp(m_pSaveDetails->SaveInfoA[sortedIdx[sj]].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[key].UTF8SaveFilename) < 0)
|
||||||
|
{
|
||||||
|
sortedIdx[sj + 1] = sortedIdx[sj];
|
||||||
|
--sj;
|
||||||
|
}
|
||||||
|
sortedIdx[sj + 1] = key;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
for(unsigned int i = 0; i < m_pSaveDetails->iSaveC; ++i)
|
for(unsigned int i = 0; i < m_pSaveDetails->iSaveC; ++i)
|
||||||
{
|
{
|
||||||
#if defined(_XBOX_ONE)
|
#if defined(_XBOX_ONE)
|
||||||
@@ -627,14 +735,40 @@ void UIScene_LoadOrJoinMenu::tick()
|
|||||||
m_saveDetails[i].saveId = i;
|
m_saveDetails[i].saveId = i;
|
||||||
memcpy(m_saveDetails[i].UTF16SaveName, m_pSaveDetails->SaveInfoA[i].UTF16SaveTitle, 128);
|
memcpy(m_saveDetails[i].UTF16SaveName, m_pSaveDetails->SaveInfoA[i].UTF16SaveTitle, 128);
|
||||||
memcpy(m_saveDetails[i].UTF16SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF16SaveFilename, MAX_SAVEFILENAME_LENGTH);
|
memcpy(m_saveDetails[i].UTF16SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF16SaveFilename, MAX_SAVEFILENAME_LENGTH);
|
||||||
|
#else
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
{
|
||||||
|
int origIdx = sortedIdx[i];
|
||||||
|
wchar_t wFilename[MAX_SAVEFILENAME_LENGTH];
|
||||||
|
ZeroMemory(wFilename, sizeof(wFilename));
|
||||||
|
mbstowcs(wFilename, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH - 1);
|
||||||
|
wstring filePath = wstring(L"Windows64\\GameHDD\\") + wstring(wFilename) + wstring(L"\\saveData.ms");
|
||||||
|
wstring levelName = ReadLevelNameFromSaveFile(filePath);
|
||||||
|
if (!levelName.empty())
|
||||||
|
{
|
||||||
|
m_buttonListSaves.addItem(levelName, wstring(L""));
|
||||||
|
wcstombs(m_saveDetails[i].UTF8SaveName, levelName.c_str(), 127);
|
||||||
|
m_saveDetails[i].UTF8SaveName[127] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveTitle, L"");
|
||||||
|
memcpy(m_saveDetails[i].UTF8SaveName, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveTitle, 128);
|
||||||
|
}
|
||||||
|
m_saveDetails[i].saveId = origIdx;
|
||||||
|
memcpy(m_saveDetails[i].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, L"");
|
m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, L"");
|
||||||
|
|
||||||
m_saveDetails[i].saveId = i;
|
|
||||||
memcpy(m_saveDetails[i].UTF8SaveName, m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, 128);
|
memcpy(m_saveDetails[i].UTF8SaveName, m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, 128);
|
||||||
|
m_saveDetails[i].saveId = i;
|
||||||
memcpy(m_saveDetails[i].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH);
|
memcpy(m_saveDetails[i].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
delete[] sortedIdx;
|
||||||
|
#endif
|
||||||
m_controlSavesTimer.setVisible( false );
|
m_controlSavesTimer.setVisible( false );
|
||||||
|
|
||||||
// set focus on the first button
|
// set focus on the first button
|
||||||
@@ -650,7 +784,11 @@ void UIScene_LoadOrJoinMenu::tick()
|
|||||||
app.DebugPrintf("Requesting the first thumbnail\n");
|
app.DebugPrintf("Requesting the first thumbnail\n");
|
||||||
// set the save to load
|
// set the save to load
|
||||||
PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo();
|
PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo();
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[m_saveDetails[m_iRequestingThumbnailId].saveId],&LoadSaveDataThumbnailReturned,this);
|
||||||
|
#else
|
||||||
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this);
|
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail)
|
if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail)
|
||||||
{
|
{
|
||||||
@@ -713,7 +851,11 @@ void UIScene_LoadOrJoinMenu::tick()
|
|||||||
app.DebugPrintf("Requesting another thumbnail\n");
|
app.DebugPrintf("Requesting another thumbnail\n");
|
||||||
// set the save to load
|
// set the save to load
|
||||||
PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo();
|
PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo();
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[m_saveDetails[m_iRequestingThumbnailId].saveId],&LoadSaveDataThumbnailReturned,this);
|
||||||
|
#else
|
||||||
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this);
|
C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this);
|
||||||
|
#endif
|
||||||
if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail)
|
if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail)
|
||||||
{
|
{
|
||||||
// something went wrong
|
// something went wrong
|
||||||
@@ -1323,7 +1465,7 @@ void UIScene_LoadOrJoinMenu::handlePress(F64 controlId, F64 childId)
|
|||||||
LoadMenuInitData *params = new LoadMenuInitData();
|
LoadMenuInitData *params = new LoadMenuInitData();
|
||||||
params->iPad = m_iPad;
|
params->iPad = m_iPad;
|
||||||
// need to get the iIndex from the list item, since the position in the list doesn't correspond to the GetSaveGameInfo list because of sorting
|
// need to get the iIndex from the list item, since the position in the list doesn't correspond to the GetSaveGameInfo list because of sorting
|
||||||
params->iSaveGameInfoIndex=((int)childId)-m_iDefaultButtonsC;
|
params->iSaveGameInfoIndex=m_saveDetails[((int)childId)-m_iDefaultButtonsC].saveId;
|
||||||
//params->pbSaveRenamed=&m_bSaveRenamed;
|
//params->pbSaveRenamed=&m_bSaveRenamed;
|
||||||
params->levelGen = NULL;
|
params->levelGen = NULL;
|
||||||
params->saveDetails = &m_saveDetails[ ((int)childId)-m_iDefaultButtonsC ];
|
params->saveDetails = &m_saveDetails[ ((int)childId)-m_iDefaultButtonsC ];
|
||||||
|
|||||||
@@ -613,7 +613,7 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW
|
|||||||
//localIp = settings->getString(L"server-ip", L"");
|
//localIp = settings->getString(L"server-ip", L"");
|
||||||
//onlineMode = settings->getBoolean(L"online-mode", true);
|
//onlineMode = settings->getBoolean(L"online-mode", true);
|
||||||
//motd = settings->getString(L"motd", L"A Minecraft Server");
|
//motd = settings->getString(L"motd", L"A Minecraft Server");
|
||||||
//motd.replace('<27>', '$');
|
//motd.replace('<27>', '$');
|
||||||
|
|
||||||
setAnimals(settings->getBoolean(L"spawn-animals", true));
|
setAnimals(settings->getBoolean(L"spawn-animals", true));
|
||||||
setNpcsEnabled(settings->getBoolean(L"spawn-npcs", true));
|
setNpcsEnabled(settings->getBoolean(L"spawn-npcs", true));
|
||||||
@@ -667,8 +667,8 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW
|
|||||||
|
|
||||||
__int64 levelNanoTime = System::nanoTime();
|
__int64 levelNanoTime = System::nanoTime();
|
||||||
|
|
||||||
wstring levelName = settings->getString(L"level-name", L"world");
|
wstring levelName = (initData && !initData->levelName.empty()) ? initData->levelName : settings->getString(L"level-name", L"world");
|
||||||
wstring levelTypeString;
|
wstring levelTypeString;
|
||||||
|
|
||||||
bool gameRuleUseFlatWorld = false;
|
bool gameRuleUseFlatWorld = false;
|
||||||
if(app.getLevelGenerationOptions() != NULL)
|
if(app.getLevelGenerationOptions() != NULL)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ typedef struct _NetworkGameInitData
|
|||||||
unsigned int xzSize;
|
unsigned int xzSize;
|
||||||
unsigned char hellScale;
|
unsigned char hellScale;
|
||||||
ESavePlatform savePlatform;
|
ESavePlatform savePlatform;
|
||||||
|
wstring levelName;
|
||||||
|
|
||||||
_NetworkGameInitData()
|
_NetworkGameInitData()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -749,7 +749,7 @@ void ConsoleSaveFileOriginal::Flush(bool autosave, bool updateThumbnail )
|
|||||||
PBYTE pbDataSaveImage=NULL;
|
PBYTE pbDataSaveImage=NULL;
|
||||||
DWORD dwDataSizeSaveImage=0;
|
DWORD dwDataSizeSaveImage=0;
|
||||||
|
|
||||||
#if ( defined _XBOX || defined _DURANGO )
|
#if ( defined _XBOX || defined _DURANGO || defined _WINDOWS64 )
|
||||||
app.GetSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize);
|
app.GetSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize);
|
||||||
#elif ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ )
|
#elif ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ )
|
||||||
app.GetSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize,&pbDataSaveImage,&dwDataSizeSaveImage);
|
app.GetSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize,&pbDataSaveImage,&dwDataSizeSaveImage);
|
||||||
|
|||||||
Reference in New Issue
Block a user