Something went wrong. Try again.
the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
Something went wrong. Try again.
8.6 kB · 299 lines
C++
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299#include "stdafx.h"#include "net.minecraft.world.level.chunk.storage.h"#include "net.minecraft.world.level.storage.h"#include "ConsoleSaveFileIO.h"#include "ConsoleSaveFileConverter.h"#include "ProgressListener.h"
void ConsoleSaveFileConverter::ProcessSimpleFile(ConsoleSaveFile *sourceSave, FileEntry *sourceFileEntry, ConsoleSaveFile *targetSave, FileEntry *targetFileEntry){ DWORD numberOfBytesRead = 0; DWORD numberOfBytesWritten = 0;
byte *data = new byte[sourceFileEntry->getFileSize()];
// Read from source sourceSave->readFile(sourceFileEntry, data, sourceFileEntry->getFileSize(), &numberOfBytesRead);
// Write back to target targetSave->writeFile(targetFileEntry, data, numberOfBytesRead, &numberOfBytesWritten);
delete [] data;}
void ConsoleSaveFileConverter::ProcessStandardRegionFile(ConsoleSaveFile *sourceSave, File sourceFile, ConsoleSaveFile *targetSave, File targetFile){ DWORD numberOfBytesWritten = 0; DWORD numberOfBytesRead = 0;
RegionFile sourceRegionFile(sourceSave, &sourceFile); RegionFile targetRegionFile(targetSave, &targetFile);
for(unsigned int x = 0; x < 32; ++x) { for(unsigned int z = 0; z < 32; ++z) { DataInputStream *dis = sourceRegionFile.getChunkDataInputStream(x,z);
if(dis) { int read = dis->read(); DataOutputStream *dos = targetRegionFile.getChunkDataOutputStream(x,z); while(read != -1) {
dos->write( read & 0xff );
read = dis->read(); } dos->close(); dos->deleteChildStream(); delete dos; }
delete dis; } }}
void ConsoleSaveFileConverter::ConvertSave(ConsoleSaveFile *sourceSave, ConsoleSaveFile *targetSave, ProgressListener *progress){ // Process level.dat ConsoleSavePath ldatPath( wstring(L"level.dat") ); FileEntry *sourceLdatFe = sourceSave->createFile( ldatPath ); FileEntry *targetLdatFe = targetSave->createFile( ldatPath ); app.DebugPrintf("Processing level.dat\n"); ProcessSimpleFile(sourceSave, sourceLdatFe, targetSave, targetLdatFe);
// Process game rules { ConsoleSavePath gameRulesPath( GAME_RULE_SAVENAME ); if(sourceSave->doesFileExist(gameRulesPath) ) { FileEntry *sourceFe = sourceSave->createFile( gameRulesPath ); FileEntry *targetFe = targetSave->createFile( gameRulesPath ); app.DebugPrintf("Processing game rules\n"); ProcessSimpleFile(sourceSave, sourceFe, targetSave, targetFe); } }
// MGH added - find any player data files and copy them across#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) vector<FileEntry *>* playerFiles = sourceSave->getValidPlayerDatFiles();#else vector<FileEntry *> *playerFiles = sourceSave->getFilesWithPrefix( DirectoryLevelStorage::getPlayerDir() );#endif
if(playerFiles != NULL) { for(int fileIdx = 0; fileIdx < playerFiles->size();fileIdx++) { ConsoleSavePath sourcePlayerDatPath( playerFiles->at(fileIdx)->data.filename );#ifdef _XBOX_ONE // 4J Stu - As the XUIDs on X360 and X1 are different, we don't want to transfer these over. However as the first player // file should be the owner of the save, we can move their data over to the current players XUID if(fileIdx > 0) break; PlayerUID xuid; ProfileManager.GetXUID(ProfileManager.GetPrimaryPad(), &xuid, false); ConsoleSavePath targetPlayerDatPath( L"players/" + xuid.toString() + L".dat" );#else ConsoleSavePath targetPlayerDatPath( playerFiles->at(fileIdx)->data.filename );#endif { FileEntry *sourceFe = sourceSave->createFile( sourcePlayerDatPath ); FileEntry *targetFe = targetSave->createFile( targetPlayerDatPath ); app.DebugPrintf("Processing player dat file %s\n", playerFiles->at(fileIdx)->data.filename); ProcessSimpleFile(sourceSave, sourceFe, targetSave, targetFe);
targetFe->data.lastModifiedTime = sourceFe->data.lastModifiedTime; } } delete playerFiles; }
#ifdef SPLIT_SAVES int xzSize = LEVEL_LEGACY_WIDTH; int hellScale = HELL_LEVEL_LEGACY_SCALE; if ( sourceSave->doesFileExist( ldatPath ) ) { ConsoleSaveFileInputStream fis = ConsoleSaveFileInputStream(sourceSave, ldatPath); CompoundTag *root = NbtIo::readCompressed(&fis); CompoundTag *tag = root->getCompound(L"Data"); LevelData ret(tag);
xzSize = ret.getXZSize(); hellScale = ret.getHellScale();
delete root; }
RegionFileCache sourceCache; RegionFileCache targetCache;
if(progress) {#ifndef _WINDOWS64 progress->progressStage(IDS_SAVETRANSFER_STAGE_CONVERTING);#endif }
// Overworld { app.DebugPrintf("Processing the overworld\n"); int halfXZSize = xzSize / 2;
int progressTarget = (xzSize) * (xzSize); int currentProgress = 0; if(progress) progress->progressStagePercentage((currentProgress*100)/progressTarget);
for(int x = -halfXZSize; x < halfXZSize; ++x) { for(int z = -halfXZSize; z < halfXZSize; ++z) { //app.DebugPrintf("Processing overworld chunk %d,%d\n",x,z); DataInputStream *dis = sourceCache._getChunkDataInputStream(sourceSave,L"",x,z);
if(dis) { int read = dis->read(); DataOutputStream *dos = targetCache._getChunkDataOutputStream(targetSave,L"",x,z); BufferedOutputStream bos(dos, 1024 * 1024); while(read != -1) {
bos.write( read & 0xff );
read = dis->read(); } bos.flush(); dos->close(); dos->deleteChildStream(); delete dos; dis->deleteChildStream(); delete dis; }
++currentProgress; if(progress) progress->progressStagePercentage( (currentProgress*100)/progressTarget);
} } }
// Nether { app.DebugPrintf("Processing the nether\n"); int hellSize = xzSize / hellScale; int halfXZSize = hellSize / 2;
int progressTarget = (hellSize) * (hellSize); int currentProgress = 0; if(progress) progress->progressStagePercentage((currentProgress*100)/progressTarget);
for(int x = -halfXZSize; x < halfXZSize; ++x) { for(int z = -halfXZSize; z < halfXZSize; ++z) { //app.DebugPrintf("Processing nether chunk %d,%d\n",x,z); DataInputStream *dis = sourceCache._getChunkDataInputStream(sourceSave,L"DIM-1",x,z);
if(dis) { int read = dis->read(); DataOutputStream *dos = targetCache._getChunkDataOutputStream(targetSave,L"DIM-1",x,z); BufferedOutputStream bos(dos, 1024 * 1024); while(read != -1) {
bos.write( read & 0xff );
read = dis->read(); } bos.flush(); dos->close(); dos->deleteChildStream(); delete dos; dis->deleteChildStream(); delete dis; }
++currentProgress; if(progress) progress->progressStagePercentage((currentProgress*100)/progressTarget); } } }
// End { app.DebugPrintf("Processing the end\n"); int halfXZSize = END_LEVEL_MAX_WIDTH / 2;
int progressTarget = (END_LEVEL_MAX_WIDTH) * (END_LEVEL_MAX_WIDTH); int currentProgress = 0; if(progress) progress->progressStagePercentage((currentProgress*100)/progressTarget);
for(int x = -halfXZSize; x < halfXZSize; ++x) { for(int z = -halfXZSize; z < halfXZSize; ++z) { //app.DebugPrintf("Processing end chunk %d,%d\n",x,z); DataInputStream *dis = sourceCache._getChunkDataInputStream(sourceSave,L"DIM1/",x,z);
if(dis) { int read = dis->read(); DataOutputStream *dos = targetCache._getChunkDataOutputStream(targetSave,L"DIM1/",x,z); BufferedOutputStream bos(dos, 1024 * 1024); while(read != -1) {
bos.write( read & 0xff );
read = dis->read(); } bos.flush(); dos->close(); dos->deleteChildStream(); delete dos; dis->deleteChildStream(); delete dis; }
++currentProgress; if(progress) progress->progressStagePercentage((currentProgress*100)/progressTarget); } } }
#else // 4J Stu - Old version that just changes the compression of chunks, not usable for XboxOne style split saves or compressed tile formats // Process region files vector<FileEntry *> *allFilesInSave = sourceSave->getFilesWithPrefix(wstring(L"")); for(AUTO_VAR(it, allFilesInSave->begin()); it < allFilesInSave->end(); ++it) { FileEntry *fe = *it; if( fe != sourceLdatFe ) { wstring fName( fe->data.filename ); wstring suffix(L".mcr"); if( fName.compare(fName.length() - suffix.length(), suffix.length(), suffix) == 0 ) {#ifndef _CONTENT_PACKAGE wprintf(L"Processing a region file: %s\n", fe->data.filename);#endif ProcessStandardRegionFile(sourceSave, File(fe->data.filename), targetSave, File(fe->data.filename) ); } else {#ifndef _CONTENT_PACKAGE wprintf(L"%s is not a region file, ignoring\n", fe->data.filename);#endif } } }#endif}