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.
11 kB · 365 lines
C++
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365#include "stdafx.h"#include "JavaMath.h"#include "BasicTypeContainers.h"#if 0// 4J - not required anymore#include "Matcher.h"#endif#include "ProgressListener.h"#include "net.minecraft.world.level.chunk.storage.h"#include "net.minecraft.world.level.chunk.h"#include "LevelSummary.h"#include "McRegionLevelStorage.h"#include "File.h"#include "LevelData.h"#include "McRegionLevelStorageSource.h"
#include "ConsoleSaveFileIO.h"
#if 0// 4J - not required anymore// These were Pattern class objects, using the c++0x regex class insteadconst std::tr1::wregex McRegionLevelStorageSource::FolderFilter::chunkFolderPattern = std::tr1::wregex(L"[0-9a-z]|([0-9a-z][0-9a-z])");const std::tr1::wregex McRegionLevelStorageSource::ChunkFilter::chunkFilePattern = std::tr1::wregex(L"c\\.(-?[0-9a-z]+)\\.(-?[0-9a-z]+)\\.dat");#endif
McRegionLevelStorageSource::McRegionLevelStorageSource(File dir) : DirectoryLevelStorageSource(dir){}
wstring McRegionLevelStorageSource::getName(){ return L"Scaevolus' McRegion";}
vector<LevelSummary *> *McRegionLevelStorageSource::getLevelList(){ // 4J Stu - We don't need to do directory lookups with the xbox save files vector<LevelSummary *> *levels = new vector<LevelSummary *>;#if 0 vector<File *> *subFolders = baseDir.listFiles(); File *file; AUTO_VAR(itEnd, subFolders->end()); for (AUTO_VAR(it, subFolders->begin()); it != itEnd; it++) { file = *it; //subFolders->at(i);
if (file->isDirectory()) { continue; }
wstring levelId = file->getName();
LevelData *levelData = getDataTagFor(levelId); if (levelData != NULL) { bool requiresConversion = levelData->getVersion() != McRegionLevelStorage::MCREGION_VERSION_ID; wstring levelName = levelData->getLevelName();
if (levelName.empty()) // 4J Jev TODO: levelName can't be NULL? if (levelName == NULL || isEmpty(levelName)) { levelName = levelId; } // long size = getLevelSize(folder); long size = 0; levels->push_back(new LevelSummary(levelId, levelName, levelData->getLastPlayed(), size, requiresConversion, levelData->isHardcore())); } }#endif return levels;}
void McRegionLevelStorageSource::clearAll(){}
shared_ptr<LevelStorage> McRegionLevelStorageSource::selectLevel(ConsoleSaveFile *saveFile, const wstring& levelId, bool createPlayerDir) { // return new LevelStorageProfilerDecorator(new McRegionLevelStorage(baseDir, levelId, createPlayerDir)); return shared_ptr<LevelStorage>(new McRegionLevelStorage(saveFile, baseDir, levelId, createPlayerDir));}
bool McRegionLevelStorageSource::isConvertible(ConsoleSaveFile *saveFile, const wstring& levelId) { // check if there is old file format level data LevelData *levelData = getDataTagFor(saveFile, levelId); if (levelData == NULL || levelData->getVersion() != 0) { delete levelData; return false; } delete levelData;
return true;}
bool McRegionLevelStorageSource::requiresConversion(ConsoleSaveFile *saveFile, const wstring& levelId){ LevelData *levelData = getDataTagFor(saveFile, levelId); if (levelData == NULL || levelData->getVersion() != 0) { delete levelData; return false; } delete levelData;
return true;}
bool McRegionLevelStorageSource::convertLevel(ConsoleSaveFile *saveFile, const wstring& levelId, ProgressListener *progress){ assert(false); // I removed this while updating the saves to use the single save file // Will we ever use this convertLevel function anyway? The main issue is the check // for the hellFolder.exists() which would require a slight change to the way our // save files are structured#if 0 progress->progressStagePercentage(0);
vector<ChunkFile *> *normalRegions = new vector<ChunkFile *>; vector<File *> *normalBaseFolders = new vector<File *>; vector<ChunkFile *> *netherRegions = new vector<ChunkFile *>; vector<File *> *netherBaseFolders = new vector<File *>; ArrayList<ChunkFile> enderRegions = new ArrayList<ChunkFile>(); ArrayList<File> enderBaseFolders = new ArrayList<File>();
//File baseFolder = File(baseDir, levelId); //File netherFolder = File(baseFolder, LevelStorage::HELL_FOLDER); //File enderFolder = new File(baseFolder, LevelStorage.ENDER_FOLDER); ConsoleSaveFile saveFile = ConsoleSaveFile( levelId );
// System.out.println("Scanning folders..."); 4J Jev, TODO how do we println ?
// find normal world addRegions(baseFolder, normalRegions, normalBaseFolders);
// find hell world if (netherFolder.exists()) { addRegions(netherFolder, netherRegions, netherBaseFolders); } if (enderFolder.exists()) { addRegions(enderFolder, enderRegions, enderBaseFolders); }
int totalCount = normalRegions->size() + netherRegions->size() + enderRegions.size() + normalBaseFolders->size() + netherBaseFolders->size() + enderBaseFolders.size(); // System.out.println("Total conversion count is " + totalCount); 4J Jev, TODO
// convert normal world convertRegions(baseFolder, normalRegions, 0, totalCount, progress); // convert hell world convertRegions(netherFolder, netherRegions, normalRegions->size(), totalCount, progress); // convert hell world convertRegions(enderFolder, enderRegions, normalRegions.size() + netherRegions.size(), totalCount, progress);
LevelData *levelData = getDataTagFor(levelId); levelData->setVersion(McRegionLevelStorage::MCREGION_VERSION_ID);
LevelStorage *levelStorage = selectLevel(levelId, false); levelStorage->saveLevelData(levelData);
// erase old files eraseFolders(normalBaseFolders, normalRegions->size() + netherRegions->size(), totalCount, progress); if (netherFolder.exists()) { eraseFolders(netherBaseFolders, normalRegions->size() + netherRegions->size() + normalBaseFolders->size(), totalCount, progress); }#endif return true;}
#if 0// 4J - not required anymorevoid McRegionLevelStorageSource::addRegions(File &baseFolder, vector<ChunkFile *> *dest, vector<File *> *firstLevelFolders) { FolderFilter folderFilter; ChunkFilter chunkFilter;
File *folder1; vector<File *> *folderLevel1 = baseFolder.listFiles((FileFilter *) &folderFilter); AUTO_VAR(itEnd, folderLevel1->end()); for (AUTO_VAR(it, folderLevel1->begin()); it != itEnd; it++) { folder1 = *it; //folderLevel1->at(i1);
// keep this for the clean-up process later on firstLevelFolders->push_back(folder1);
File *folder2; vector<File *> *folderLevel2 = folder1->listFiles(&folderFilter); AUTO_VAR(itEnd2, folderLevel2->end()); for (AUTO_VAR(it2, folderLevel2->begin()); it2 != itEnd; it2++) { folder2 = *it2; //folderLevel2->at(i2);
vector<File *> *chunkFiles = folder2->listFiles((FileFilter *) &chunkFilter);
File *chunk; AUTO_VAR(itEndFile, chunkFiles->end()); for (AUTO_VAR(itFile, chunkFiles->begin()); itFile != itEndFile; itFile++) { chunk = *itFile; //chunkFiles->at(i3);
dest->push_back(new ChunkFile(chunk)); } } }}#endif
void McRegionLevelStorageSource::convertRegions(File &baseFolder, vector<ChunkFile *> *chunkFiles, int currentCount, int totalCount, ProgressListener *progress) { assert( false );
// 4J Stu - Removed, see comment in convertLevel above#if 0 //Collections::sort(chunkFiles); std::sort( chunkFiles->begin(), chunkFiles->end() );
byteArray buffer = byteArray(4096);
ChunkFile *chunkFile; AUTO_VAR(itEnd, chunkFiles->end()); for (AUTO_VAR(it, chunkFiles->begin()); it != itEnd; it++) { chunkFile = *it; //chunkFiles->at(i1);
// Matcher matcher = ChunkFilter.chunkFilePattern.matcher(chunkFile.getName()); // if (!matcher.matches()) { // continue; // } // int x = Integer.parseInt(matcher.group(1), 36); // int z = Integer.parseInt(matcher.group(2), 36);
int x = chunkFile->getX(); int z = chunkFile->getZ();
RegionFile *region = RegionFileCache::getRegionFile(baseFolder, x, z); if (!region->hasChunk(x & 31, z & 31)) { FileInputStream fis = new BufferedInputStream(FileInputStream(*chunkFile->getFile())); DataInputStream istream = DataInputStream(&fis); // 4J - was new GZIPInputStream as well
DataOutputStream *out = region->getChunkDataOutputStream(x & 31, z & 31);
int length = 0; while ( (length = istream.read(buffer)) != -1 ) { out->write(buffer, 0, length); }
out->close(); istream.close();
// 4J Stu - getChunkDataOutputStream makes a new DataOutputStream that points to a new ChunkBuffer( ByteArrayOutputStream ) // We should clean these up when we are done out->deleteChildStream(); delete out; }
currentCount++; int percent = (int) Math::round(100.0 * (double) currentCount / (double) totalCount); progress->progressStagePercentage(percent); } RegionFileCache::clear();#endif
}
void McRegionLevelStorageSource::eraseFolders(vector<File *> *folders, int currentCount, int totalCount, ProgressListener *progress){ File *folder; AUTO_VAR(itEnd, folders->end()); for (AUTO_VAR(it, folders->begin()); it != itEnd; it++) { folder = *it; //folders->at(i);
vector<File *> *files = folder->listFiles(); deleteRecursive(files); folder->_delete();
currentCount++; int percent = (int) Math::round(100.0 * (double) currentCount / (double) totalCount); progress->progressStagePercentage(percent); }}
#if 0// 4J - not required anymorebool McRegionLevelStorageSource::FolderFilter::accept(File *file) { if (file->isDirectory()) { Matcher matcher( chunkFolderPattern, file->getName() ); return matcher.matches(); } return false;}
bool McRegionLevelStorageSource::ChunkFilter::accept(File *dir, const wstring& name) { Matcher matcher( chunkFilePattern, name ); return matcher.matches();}
McRegionLevelStorageSource::ChunkFile::ChunkFile(File *file) { this->file = file;
Matcher matcher( ChunkFilter::chunkFilePattern, file->getName() ); if (matcher.matches()) { x = Integer::parseInt(matcher.group(1), 36); z = Integer::parseInt(matcher.group(2), 36); } else { x = 0; z = 0; }}
//Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.int McRegionLevelStorageSource::ChunkFile::compareTo(ChunkFile *rhs){ // sort chunk files so that they are placed according to their // region position int rx = x >> 5; int rhsrx = rhs->x >> 5; if (rx == rhsrx) { int rz = z >> 5; int rhsrz = rhs->z >> 5; return rz - rhsrz; }
return rx - rhsrx;}
// 4J Stu Added so we can use std::sort instead of the java Collections::sort// a < bbool McRegionLevelStorageSource::ChunkFile::operator<( ChunkFile *b ){ return compareTo( b ) < 0;}
File *McRegionLevelStorageSource::ChunkFile::getFile() { return (File *) file;}
int McRegionLevelStorageSource::ChunkFile::getX() { return x;}
int McRegionLevelStorageSource::ChunkFile::getZ() { return z;}#endif