the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 365 lines 11 kB view raw
1#include "stdafx.h" 2#include "JavaMath.h" 3#include "BasicTypeContainers.h" 4#if 0 5// 4J - not required anymore 6#include "Matcher.h" 7#endif 8#include "ProgressListener.h" 9#include "net.minecraft.world.level.chunk.storage.h" 10#include "net.minecraft.world.level.chunk.h" 11#include "LevelSummary.h" 12#include "McRegionLevelStorage.h" 13#include "File.h" 14#include "LevelData.h" 15#include "McRegionLevelStorageSource.h" 16 17#include "ConsoleSaveFileIO.h" 18 19#if 0 20// 4J - not required anymore 21// These were Pattern class objects, using the c++0x regex class instead 22const std::tr1::wregex McRegionLevelStorageSource::FolderFilter::chunkFolderPattern = std::tr1::wregex(L"[0-9a-z]|([0-9a-z][0-9a-z])"); 23const std::tr1::wregex McRegionLevelStorageSource::ChunkFilter::chunkFilePattern = std::tr1::wregex(L"c\\.(-?[0-9a-z]+)\\.(-?[0-9a-z]+)\\.dat"); 24#endif 25 26McRegionLevelStorageSource::McRegionLevelStorageSource(File dir) : DirectoryLevelStorageSource(dir) 27{ 28} 29 30wstring McRegionLevelStorageSource::getName() 31{ 32 return L"Scaevolus' McRegion"; 33} 34 35vector<LevelSummary *> *McRegionLevelStorageSource::getLevelList() 36{ 37 // 4J Stu - We don't need to do directory lookups with the xbox save files 38 vector<LevelSummary *> *levels = new vector<LevelSummary *>; 39#if 0 40 vector<File *> *subFolders = baseDir.listFiles(); 41 File *file; 42 AUTO_VAR(itEnd, subFolders->end()); 43 for (AUTO_VAR(it, subFolders->begin()); it != itEnd; it++) 44 { 45 file = *it; //subFolders->at(i); 46 47 if (file->isDirectory()) 48 { 49 continue; 50 } 51 52 wstring levelId = file->getName(); 53 54 LevelData *levelData = getDataTagFor(levelId); 55 if (levelData != NULL) 56 { 57 bool requiresConversion = levelData->getVersion() != McRegionLevelStorage::MCREGION_VERSION_ID; 58 wstring levelName = levelData->getLevelName(); 59 60 if (levelName.empty()) // 4J Jev TODO: levelName can't be NULL? if (levelName == NULL || isEmpty(levelName)) 61 { 62 levelName = levelId; 63 } 64 // long size = getLevelSize(folder); 65 long size = 0; 66 levels->push_back(new LevelSummary(levelId, levelName, levelData->getLastPlayed(), size, requiresConversion, levelData->isHardcore())); 67 } 68 } 69#endif 70 return levels; 71} 72 73void McRegionLevelStorageSource::clearAll() 74{ 75} 76 77shared_ptr<LevelStorage> McRegionLevelStorageSource::selectLevel(ConsoleSaveFile *saveFile, const wstring& levelId, bool createPlayerDir) 78{ 79 // return new LevelStorageProfilerDecorator(new McRegionLevelStorage(baseDir, levelId, createPlayerDir)); 80 return shared_ptr<LevelStorage>(new McRegionLevelStorage(saveFile, baseDir, levelId, createPlayerDir)); 81} 82 83bool McRegionLevelStorageSource::isConvertible(ConsoleSaveFile *saveFile, const wstring& levelId) 84{ 85 // check if there is old file format level data 86 LevelData *levelData = getDataTagFor(saveFile, levelId); 87 if (levelData == NULL || levelData->getVersion() != 0) 88 { 89 delete levelData; 90 return false; 91 } 92 delete levelData; 93 94 return true; 95} 96 97bool McRegionLevelStorageSource::requiresConversion(ConsoleSaveFile *saveFile, const wstring& levelId) 98{ 99 LevelData *levelData = getDataTagFor(saveFile, levelId); 100 if (levelData == NULL || levelData->getVersion() != 0) 101 { 102 delete levelData; 103 return false; 104 } 105 delete levelData; 106 107 return true; 108} 109 110bool McRegionLevelStorageSource::convertLevel(ConsoleSaveFile *saveFile, const wstring& levelId, ProgressListener *progress) 111{ 112 assert(false); 113 // I removed this while updating the saves to use the single save file 114 // Will we ever use this convertLevel function anyway? The main issue is the check 115 // for the hellFolder.exists() which would require a slight change to the way our 116 // save files are structured 117#if 0 118 progress->progressStagePercentage(0); 119 120 vector<ChunkFile *> *normalRegions = new vector<ChunkFile *>; 121 vector<File *> *normalBaseFolders = new vector<File *>; 122 vector<ChunkFile *> *netherRegions = new vector<ChunkFile *>; 123 vector<File *> *netherBaseFolders = new vector<File *>; 124 ArrayList<ChunkFile> enderRegions = new ArrayList<ChunkFile>(); 125 ArrayList<File> enderBaseFolders = new ArrayList<File>(); 126 127 //File baseFolder = File(baseDir, levelId); 128 //File netherFolder = File(baseFolder, LevelStorage::HELL_FOLDER); 129 //File enderFolder = new File(baseFolder, LevelStorage.ENDER_FOLDER); 130 ConsoleSaveFile saveFile = ConsoleSaveFile( levelId ); 131 132 // System.out.println("Scanning folders..."); 4J Jev, TODO how do we println ? 133 134 // find normal world 135 addRegions(baseFolder, normalRegions, normalBaseFolders); 136 137 // find hell world 138 if (netherFolder.exists()) 139 { 140 addRegions(netherFolder, netherRegions, netherBaseFolders); 141 } 142 if (enderFolder.exists()) 143 { 144 addRegions(enderFolder, enderRegions, enderBaseFolders); 145 } 146 147 int totalCount = normalRegions->size() + netherRegions->size() + enderRegions.size() + normalBaseFolders->size() + netherBaseFolders->size() + enderBaseFolders.size(); 148 149 // System.out.println("Total conversion count is " + totalCount); 4J Jev, TODO 150 151 // convert normal world 152 convertRegions(baseFolder, normalRegions, 0, totalCount, progress); 153 // convert hell world 154 convertRegions(netherFolder, netherRegions, normalRegions->size(), totalCount, progress); 155 // convert hell world 156 convertRegions(enderFolder, enderRegions, normalRegions.size() + netherRegions.size(), totalCount, progress); 157 158 LevelData *levelData = getDataTagFor(levelId); 159 levelData->setVersion(McRegionLevelStorage::MCREGION_VERSION_ID); 160 161 LevelStorage *levelStorage = selectLevel(levelId, false); 162 levelStorage->saveLevelData(levelData); 163 164 // erase old files 165 eraseFolders(normalBaseFolders, normalRegions->size() + netherRegions->size(), totalCount, progress); 166 if (netherFolder.exists()) 167 { 168 eraseFolders(netherBaseFolders, normalRegions->size() + netherRegions->size() + normalBaseFolders->size(), totalCount, progress); 169 } 170#endif 171 return true; 172} 173 174#if 0 175// 4J - not required anymore 176void McRegionLevelStorageSource::addRegions(File &baseFolder, vector<ChunkFile *> *dest, vector<File *> *firstLevelFolders) 177{ 178 FolderFilter folderFilter; 179 ChunkFilter chunkFilter; 180 181 File *folder1; 182 vector<File *> *folderLevel1 = baseFolder.listFiles((FileFilter *) &folderFilter); 183 AUTO_VAR(itEnd, folderLevel1->end()); 184 for (AUTO_VAR(it, folderLevel1->begin()); it != itEnd; it++) 185 { 186 folder1 = *it; //folderLevel1->at(i1); 187 188 // keep this for the clean-up process later on 189 firstLevelFolders->push_back(folder1); 190 191 File *folder2; 192 vector<File *> *folderLevel2 = folder1->listFiles(&folderFilter); 193 AUTO_VAR(itEnd2, folderLevel2->end()); 194 for (AUTO_VAR(it2, folderLevel2->begin()); it2 != itEnd; it2++) 195 { 196 folder2 = *it2; //folderLevel2->at(i2); 197 198 vector<File *> *chunkFiles = folder2->listFiles((FileFilter *) &chunkFilter); 199 200 File *chunk; 201 AUTO_VAR(itEndFile, chunkFiles->end()); 202 for (AUTO_VAR(itFile, chunkFiles->begin()); itFile != itEndFile; itFile++) 203 { 204 chunk = *itFile; //chunkFiles->at(i3); 205 206 dest->push_back(new ChunkFile(chunk)); 207 } 208 } 209 } 210} 211#endif 212 213void McRegionLevelStorageSource::convertRegions(File &baseFolder, vector<ChunkFile *> *chunkFiles, int currentCount, int totalCount, ProgressListener *progress) 214{ 215 assert( false ); 216 217 // 4J Stu - Removed, see comment in convertLevel above 218#if 0 219 //Collections::sort(chunkFiles); 220 std::sort( chunkFiles->begin(), chunkFiles->end() ); 221 222 byteArray buffer = byteArray(4096); 223 224 ChunkFile *chunkFile; 225 AUTO_VAR(itEnd, chunkFiles->end()); 226 for (AUTO_VAR(it, chunkFiles->begin()); it != itEnd; it++) 227 { 228 chunkFile = *it; //chunkFiles->at(i1); 229 230 // Matcher matcher = ChunkFilter.chunkFilePattern.matcher(chunkFile.getName()); 231 // if (!matcher.matches()) { 232 // continue; 233 // } 234 // int x = Integer.parseInt(matcher.group(1), 36); 235 // int z = Integer.parseInt(matcher.group(2), 36); 236 237 int x = chunkFile->getX(); 238 int z = chunkFile->getZ(); 239 240 RegionFile *region = RegionFileCache::getRegionFile(baseFolder, x, z); 241 if (!region->hasChunk(x & 31, z & 31)) 242 { 243 FileInputStream fis = new BufferedInputStream(FileInputStream(*chunkFile->getFile())); 244 DataInputStream istream = DataInputStream(&fis); // 4J - was new GZIPInputStream as well 245 246 DataOutputStream *out = region->getChunkDataOutputStream(x & 31, z & 31); 247 248 int length = 0; 249 while ( (length = istream.read(buffer)) != -1 ) 250 { 251 out->write(buffer, 0, length); 252 } 253 254 out->close(); 255 istream.close(); 256 257 // 4J Stu - getChunkDataOutputStream makes a new DataOutputStream that points to a new ChunkBuffer( ByteArrayOutputStream ) 258 // We should clean these up when we are done 259 out->deleteChildStream(); 260 delete out; 261 } 262 263 currentCount++; 264 int percent = (int) Math::round(100.0 * (double) currentCount / (double) totalCount); 265 progress->progressStagePercentage(percent); 266 } 267 RegionFileCache::clear(); 268#endif 269 270} 271 272void McRegionLevelStorageSource::eraseFolders(vector<File *> *folders, int currentCount, int totalCount, ProgressListener *progress) 273{ 274 File *folder; 275 AUTO_VAR(itEnd, folders->end()); 276 for (AUTO_VAR(it, folders->begin()); it != itEnd; it++) 277 { 278 folder = *it; //folders->at(i); 279 280 vector<File *> *files = folder->listFiles(); 281 deleteRecursive(files); 282 folder->_delete(); 283 284 currentCount++; 285 int percent = (int) Math::round(100.0 * (double) currentCount / (double) totalCount); 286 progress->progressStagePercentage(percent); 287 } 288} 289 290#if 0 291// 4J - not required anymore 292bool McRegionLevelStorageSource::FolderFilter::accept(File *file) 293{ 294 if (file->isDirectory()) 295 { 296 Matcher matcher( chunkFolderPattern, file->getName() ); 297 return matcher.matches(); 298 } 299 return false; 300} 301 302 303bool McRegionLevelStorageSource::ChunkFilter::accept(File *dir, const wstring& name) 304{ 305 Matcher matcher( chunkFilePattern, name ); 306 return matcher.matches(); 307} 308 309 310McRegionLevelStorageSource::ChunkFile::ChunkFile(File *file) 311{ 312 this->file = file; 313 314 Matcher matcher( ChunkFilter::chunkFilePattern, file->getName() ); 315 if (matcher.matches()) 316 { 317 x = Integer::parseInt(matcher.group(1), 36); 318 z = Integer::parseInt(matcher.group(2), 36); 319 } 320 else 321 { 322 x = 0; 323 z = 0; 324 } 325} 326 327//Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. 328int McRegionLevelStorageSource::ChunkFile::compareTo(ChunkFile *rhs) 329{ 330 // sort chunk files so that they are placed according to their 331 // region position 332 int rx = x >> 5; 333 int rhsrx = rhs->x >> 5; 334 if (rx == rhsrx) 335 { 336 int rz = z >> 5; 337 int rhsrz = rhs->z >> 5; 338 return rz - rhsrz; 339 } 340 341 return rx - rhsrx; 342} 343 344// 4J Stu Added so we can use std::sort instead of the java Collections::sort 345// a < b 346bool McRegionLevelStorageSource::ChunkFile::operator<( ChunkFile *b ) 347{ 348 return compareTo( b ) < 0; 349} 350 351File *McRegionLevelStorageSource::ChunkFile::getFile() 352{ 353 return (File *) file; 354} 355 356int McRegionLevelStorageSource::ChunkFile::getX() 357{ 358 return x; 359} 360 361int McRegionLevelStorageSource::ChunkFile::getZ() 362{ 363 return z; 364} 365#endif