the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 821 lines 24 kB view raw
1#include "stdafx.h" 2#include "System.h" 3#include "net.minecraft.world.entity.player.h" 4#include "net.minecraft.world.level.h" 5#include "net.minecraft.world.level.chunk.storage.h" 6#include "net.minecraft.world.level.dimension.h" 7#include "com.mojang.nbt.h" 8#include "File.h" 9#include "DataInputStream.h" 10#include "FileInputStream.h" 11#include "LevelData.h" 12#include "DirectoryLevelStorage.h" 13#include "ConsoleSaveFileIO.h" 14 15const wstring DirectoryLevelStorage::sc_szPlayerDir(L"players/"); 16 17_MapDataMappings::_MapDataMappings() 18{ 19#ifndef _DURANGO 20 ZeroMemory(xuids,sizeof(PlayerUID)*MAXIMUM_MAP_SAVE_DATA); 21#endif 22 ZeroMemory(dimensions,sizeof(byte)*(MAXIMUM_MAP_SAVE_DATA/4)); 23} 24 25int _MapDataMappings::getDimension(int id) 26{ 27 int offset = (2*(id%4)); 28 int val = (dimensions[id>>2] & (3 << offset))>>offset; 29 30 int returnVal=0; 31 32 switch(val) 33 { 34 case 0: 35 returnVal = 0; // Overworld 36 break; 37 case 1: 38 returnVal = -1; // Nether 39 break; 40 case 2: 41 returnVal = 1; // End 42 break; 43 default: 44#ifndef _CONTENT_PACKAGE 45 printf("Read invalid dimension from MapDataMapping\n"); 46 __debugbreak(); 47#endif 48 break; 49 } 50 return returnVal; 51} 52 53void _MapDataMappings::setMapping(int id, PlayerUID xuid, int dimension) 54{ 55 xuids[id] = xuid; 56 57 int offset = (2*(id%4)); 58 59 // Reset it first 60 dimensions[id>>2] &= ~( 2 << offset ); 61 switch(dimension) 62 { 63 case 0: // Overworld 64 //dimensions[id>>2] &= ~( 2 << offset ); 65 break; 66 case -1: // Nether 67 dimensions[id>>2] |= ( 1 << offset ); 68 break; 69 case 1: // End 70 dimensions[id>>2] |= ( 2 << offset ); 71 break; 72 default: 73#ifndef _CONTENT_PACKAGE 74 printf("Trinyg to set a MapDataMapping for an invalid dimension.\n"); 75 __debugbreak(); 76#endif 77 break; 78 } 79} 80 81// Old version the only used 1 bit for dimension indexing 82_MapDataMappings_old::_MapDataMappings_old() 83{ 84#ifndef _DURANGO 85 ZeroMemory(xuids,sizeof(PlayerUID)*MAXIMUM_MAP_SAVE_DATA); 86#endif 87 ZeroMemory(dimensions,sizeof(byte)*(MAXIMUM_MAP_SAVE_DATA/8)); 88} 89 90int _MapDataMappings_old::getDimension(int id) 91{ 92 return dimensions[id>>3] & (128 >> (id%8) ) ? -1 : 0; 93} 94 95void _MapDataMappings_old::setMapping(int id, PlayerUID xuid, int dimension) 96{ 97 xuids[id] = xuid; 98 if( dimension == 0 ) 99 { 100 dimensions[id>>3] &= ~( 128 >> (id%8) ); 101 } 102 else 103 { 104 dimensions[id>>3] |= ( 128 >> (id%8) ); 105 } 106} 107 108#ifdef _LARGE_WORLDS 109void DirectoryLevelStorage::PlayerMappings::addMapping(int id, int centreX, int centreZ, int dimension, int scale) 110{ 111 __int64 index = ( ((__int64)(centreZ & 0x1FFFFFFF)) << 34) | ( ((__int64)(centreX & 0x1FFFFFFF)) << 5) | ( (scale & 0x7) << 2) | (dimension & 0x3); 112 m_mappings[index] = id; 113 //app.DebugPrintf("Adding mapping: %d - (%d,%d)/%d/%d [%I64d - 0x%016llx]\n", id, centreX, centreZ, dimension, scale, index, index); 114} 115 116bool DirectoryLevelStorage::PlayerMappings::getMapping(int &id, int centreX, int centreZ, int dimension, int scale) 117{ 118 //__int64 zMasked = centreZ & 0x1FFFFFFF; 119 //__int64 xMasked = centreX & 0x1FFFFFFF; 120 //__int64 zShifted = zMasked << 34; 121 //__int64 xShifted = xMasked << 5; 122 //app.DebugPrintf("xShifted = %d (0x%016x), zShifted = %I64d (0x%016llx)\n", xShifted, xShifted, zShifted, zShifted); 123 __int64 index = ( ((__int64)(centreZ & 0x1FFFFFFF)) << 34) | ( ((__int64)(centreX & 0x1FFFFFFF)) << 5) | ( (scale & 0x7) << 2) | (dimension & 0x3); 124 AUTO_VAR(it,m_mappings.find(index)); 125 if(it != m_mappings.end()) 126 { 127 id = it->second; 128 //app.DebugPrintf("Found mapping: %d - (%d,%d)/%d/%d [%I64d - 0x%016llx]\n", id, centreX, centreZ, dimension, scale, index, index); 129 return true; 130 } 131 else 132 { 133 //app.DebugPrintf("Failed to find mapping: (%d,%d)/%d/%d [%I64d - 0x%016llx]\n", centreX, centreZ, dimension, scale, index, index); 134 return false; 135 } 136} 137 138void DirectoryLevelStorage::PlayerMappings::writeMappings(DataOutputStream *dos) 139{ 140 dos->writeInt(m_mappings.size()); 141 for(AUTO_VAR(it, m_mappings.begin()); it != m_mappings.end(); ++it) 142 { 143 app.DebugPrintf(" -- %lld (0x%016llx) = %d\n", it->first, it->first, it->second); 144 dos->writeLong(it->first); 145 dos->writeInt(it->second); 146 } 147} 148 149void DirectoryLevelStorage::PlayerMappings::readMappings(DataInputStream *dis) 150{ 151 int count = dis->readInt(); 152 for(unsigned int i = 0; i < count; ++i) 153 { 154 __int64 index = dis->readLong(); 155 int id = dis->readInt(); 156 m_mappings[index] = id; 157 app.DebugPrintf(" -- %lld (0x%016llx) = %d\n", index, index, id); 158 } 159} 160#endif 161 162DirectoryLevelStorage::DirectoryLevelStorage(ConsoleSaveFile *saveFile, const File dir, const wstring& levelId, bool createPlayerDir) : sessionId( System::currentTimeMillis() ), 163 dir( L"" ), playerDir( sc_szPlayerDir ), dataDir( wstring(L"data/") ), levelId(levelId) 164{ 165 m_saveFile = saveFile; 166 m_bHasLoadedMapDataMappings = false; 167 168#ifdef _LARGE_WORLDS 169 m_usedMappings = byteArray(MAXIMUM_MAP_SAVE_DATA/8); 170#endif 171} 172 173DirectoryLevelStorage::~DirectoryLevelStorage() 174{ 175 delete m_saveFile; 176 177 for(AUTO_VAR(it,m_cachedSaveData.begin()); it != m_cachedSaveData.end(); ++it) 178 { 179 delete it->second; 180 } 181 182#ifdef _LARGE_WORLDS 183 delete m_usedMappings.data; 184#endif 185} 186 187void DirectoryLevelStorage::initiateSession() 188{ 189 // 4J Jev, removed try/catch. 190 191 File dataFile = File( dir, wstring(L"session.lock") ); 192 FileOutputStream fos = FileOutputStream(dataFile); 193 DataOutputStream dos = DataOutputStream(&fos); 194 dos.writeLong(sessionId); 195 dos.close(); 196 197} 198 199File DirectoryLevelStorage::getFolder() 200{ 201 return dir; 202} 203 204void DirectoryLevelStorage::checkSession() 205{ 206 // 4J-PB - Not in the Xbox game 207 208 /* 209 File dataFile = File( dir, wstring(L"session.lock")); 210 FileInputStream fis = FileInputStream(dataFile); 211 DataInputStream dis = DataInputStream(&fis); 212 dis.close(); 213 */ 214} 215 216ChunkStorage *DirectoryLevelStorage::createChunkStorage(Dimension *dimension) 217{ 218 // 4J Jev, removed try/catch. 219 220 if (dynamic_cast<HellDimension *>(dimension) != NULL) 221 { 222 File dir2 = File(dir, LevelStorage::NETHER_FOLDER); 223 //dir2.mkdirs(); // 4J Removed 224 return new OldChunkStorage(dir2, true); 225 } 226 if (dynamic_cast<TheEndDimension *>(dimension) != NULL) 227 { 228 File dir2 = File(dir, LevelStorage::ENDER_FOLDER); 229 //dir2.mkdirs(); // 4J Removed 230 return new OldChunkStorage(dir2, true); 231 } 232 233 return new OldChunkStorage(dir, true); 234} 235 236LevelData *DirectoryLevelStorage::prepareLevel() 237{ 238 // 4J Stu Added 239#ifdef _LARGE_WORLDS 240 ConsoleSavePath mapFile = getDataFile(L"largeMapDataMappings"); 241#else 242 ConsoleSavePath mapFile = getDataFile(L"mapDataMappings"); 243#endif 244 if (!m_bHasLoadedMapDataMappings && !mapFile.getName().empty() && getSaveFile()->doesFileExist( mapFile )) 245 { 246 DWORD NumberOfBytesRead; 247 FileEntry *fileEntry = getSaveFile()->createFile(mapFile); 248 249#ifdef __PS3__ 250 // 4J Stu - This version changed happened before initial release 251 if(getSaveFile()->getSaveVersion() < SAVE_FILE_VERSION_CHANGE_MAP_DATA_MAPPING_SIZE) 252 { 253 // Delete the old file 254 if(fileEntry) getSaveFile()->deleteFile( fileEntry ); 255 256 // Save a new, blank version 257 saveMapIdLookup(); 258 } 259 else 260#elif defined(_DURANGO) 261 // 4J Stu - This version changed happened before initial release 262 if(getSaveFile()->getSaveVersion() < SAVE_FILE_VERSION_DURANGO_CHANGE_MAP_DATA_MAPPING_SIZE) 263 { 264 // Delete the old file 265 if(fileEntry) getSaveFile()->deleteFile( fileEntry ); 266 267 // Save a new, blank version 268 saveMapIdLookup(); 269 } 270 else 271#endif 272 { 273 getSaveFile()->setFilePointer(fileEntry,0,NULL, FILE_BEGIN); 274 275#ifdef _LARGE_WORLDS 276 byteArray data(fileEntry->getFileSize()); 277 getSaveFile()->readFile( fileEntry, data.data, fileEntry->getFileSize(), &NumberOfBytesRead); 278 assert( NumberOfBytesRead == fileEntry->getFileSize() ); 279 280 ByteArrayInputStream bais(data); 281 DataInputStream dis(&bais); 282 int count = dis.readInt(); 283 app.DebugPrintf("Loading %d mappings\n", count); 284 for(unsigned int i = 0; i < count; ++i) 285 { 286 PlayerUID playerUid = dis.readPlayerUID(); 287#ifdef _WINDOWS64 288 app.DebugPrintf(" -- %d\n", playerUid); 289#else 290 app.DebugPrintf(" -- %ls\n", playerUid.toString().c_str()); 291#endif 292 m_playerMappings[playerUid].readMappings(&dis); 293 } 294 dis.readFully(m_usedMappings); 295#else 296 297 if(getSaveFile()->getSaveVersion() < END_DIMENSION_MAP_MAPPINGS_SAVE_VERSION) 298 { 299 MapDataMappings_old oldMapDataMappings; 300 getSaveFile()->readFile( fileEntry, 301 &oldMapDataMappings, // data buffer 302 sizeof(MapDataMappings_old), // number of bytes to read 303 &NumberOfBytesRead // number of bytes read 304 ); 305 assert( NumberOfBytesRead == sizeof(MapDataMappings_old) ); 306 307 for(unsigned int i = 0; i < MAXIMUM_MAP_SAVE_DATA; ++i) 308 { 309 m_saveableMapDataMappings.setMapping(i,oldMapDataMappings.xuids[i],oldMapDataMappings.getDimension(i)); 310 } 311 } 312 else 313 { 314 getSaveFile()->readFile( fileEntry, 315 &m_saveableMapDataMappings, // data buffer 316 sizeof(MapDataMappings), // number of bytes to read 317 &NumberOfBytesRead // number of bytes read 318 ); 319 assert( NumberOfBytesRead == sizeof(MapDataMappings) ); 320 } 321 322 memcpy(&m_mapDataMappings,&m_saveableMapDataMappings,sizeof(MapDataMappings)); 323#endif 324 325 326 // Write out our changes now 327 if(getSaveFile()->getSaveVersion() < END_DIMENSION_MAP_MAPPINGS_SAVE_VERSION) saveMapIdLookup(); 328 } 329 330 m_bHasLoadedMapDataMappings = true; 331 } 332 333 // 4J Jev, removed try/catch 334 335 ConsoleSavePath dataFile = ConsoleSavePath( wstring( L"level.dat" ) ); 336 337 if ( m_saveFile->doesFileExist( dataFile ) ) 338 { 339 ConsoleSaveFileInputStream fis = ConsoleSaveFileInputStream(m_saveFile, dataFile); 340 CompoundTag *root = NbtIo::readCompressed(&fis); 341 CompoundTag *tag = root->getCompound(L"Data"); 342 LevelData *ret = new LevelData(tag); 343 delete root; 344 return ret; 345 } 346 347 return NULL; 348} 349 350void DirectoryLevelStorage::saveLevelData(LevelData *levelData, vector<shared_ptr<Player> > *players) 351{ 352 // 4J Jev, removed try/catch 353 354 CompoundTag *dataTag = levelData->createTag(players); 355 356 CompoundTag *root = new CompoundTag(); 357 root->put(L"Data", dataTag); 358 359 ConsoleSavePath currentFile = ConsoleSavePath( wstring( L"level.dat" ) ); 360 361 ConsoleSaveFileOutputStream fos = ConsoleSaveFileOutputStream( m_saveFile, currentFile ); 362 NbtIo::writeCompressed(root, &fos); 363 364 delete root; 365} 366 367void DirectoryLevelStorage::saveLevelData(LevelData *levelData) 368{ 369 // 4J Jev, removed try/catch 370 371 CompoundTag *dataTag = levelData->createTag(); 372 373 CompoundTag *root = new CompoundTag(); 374 root->put(L"Data", dataTag); 375 376 ConsoleSavePath currentFile = ConsoleSavePath( wstring( L"level.dat" ) ); 377 378 ConsoleSaveFileOutputStream fos = ConsoleSaveFileOutputStream( m_saveFile, currentFile ); 379 NbtIo::writeCompressed(root, &fos); 380 381 delete root; 382} 383 384void DirectoryLevelStorage::save(shared_ptr<Player> player) 385{ 386 // 4J Jev, removed try/catch. 387 PlayerUID playerXuid = player->getXuid(); 388#if defined(__PS3__) || defined(__ORBIS__) 389 if( playerXuid != INVALID_XUID ) 390#else 391 if( playerXuid != INVALID_XUID && !player->isGuest() ) 392#endif 393 { 394 CompoundTag *tag = new CompoundTag(); 395 player->saveWithoutId(tag); 396#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) 397 ConsoleSavePath realFile = ConsoleSavePath( m_saveFile->getPlayerDataFilenameForSave(playerXuid).c_str() ); 398#elif defined(_DURANGO) 399 ConsoleSavePath realFile = ConsoleSavePath( playerDir.getName() + player->getXuid().toString() + L".dat" ); 400#else 401 ConsoleSavePath realFile = ConsoleSavePath( playerDir.getName() + _toString( player->getXuid() ) + L".dat" ); 402#endif 403 // If saves are disabled (e.g. because we are writing the save buffer to disk) then cache this player data 404 if(StorageManager.GetSaveDisabled()) 405 { 406 ByteArrayOutputStream *bos = new ByteArrayOutputStream(); 407 NbtIo::writeCompressed(tag,bos); 408 409 AUTO_VAR(it, m_cachedSaveData.find(realFile.getName())); 410 if(it != m_cachedSaveData.end() ) 411 { 412 delete it->second; 413 } 414 m_cachedSaveData[realFile.getName()] = bos; 415 app.DebugPrintf("Cached saving of file %ls due to saves being disabled\n", realFile.getName().c_str() ); 416 } 417 else 418 { 419 ConsoleSaveFileOutputStream fos = ConsoleSaveFileOutputStream( m_saveFile, realFile ); 420 NbtIo::writeCompressed(tag, &fos); 421 } 422 delete tag; 423 } 424 else if( playerXuid != INVALID_XUID ) 425 { 426 app.DebugPrintf("Not saving player as their XUID is a guest\n"); 427 dontSaveMapMappingForPlayer(playerXuid); 428 } 429} 430 431// 4J Changed return val to bool to check if new player or loaded player 432CompoundTag *DirectoryLevelStorage::load(shared_ptr<Player> player) 433{ 434 CompoundTag *tag = loadPlayerDataTag( player->getXuid() ); 435 if (tag != NULL) 436 { 437 player->load(tag); 438 } 439 return tag; 440} 441 442CompoundTag *DirectoryLevelStorage::loadPlayerDataTag(PlayerUID xuid) 443{ 444 // 4J Jev, removed try/catch. 445#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) 446 ConsoleSavePath realFile = ConsoleSavePath( m_saveFile->getPlayerDataFilenameForLoad(xuid).c_str() ); 447#elif defined(_DURANGO) 448 ConsoleSavePath realFile = ConsoleSavePath( playerDir.getName() + xuid.toString() + L".dat" ); 449#else 450 ConsoleSavePath realFile = ConsoleSavePath( playerDir.getName() + _toString( xuid ) + L".dat" ); 451#endif 452 AUTO_VAR(it, m_cachedSaveData.find(realFile.getName())); 453 if(it != m_cachedSaveData.end() ) 454 { 455 ByteArrayOutputStream *bos = it->second; 456 ByteArrayInputStream bis(bos->buf, 0, bos->size()); 457 CompoundTag *tag = NbtIo::readCompressed(&bis); 458 bis.reset(); 459 app.DebugPrintf("Loaded player data from cached file %ls\n", realFile.getName().c_str() ); 460 return tag; 461 } 462 else if ( m_saveFile->doesFileExist( realFile ) ) 463 { 464 ConsoleSaveFileInputStream fis = ConsoleSaveFileInputStream(m_saveFile, realFile); 465 return NbtIo::readCompressed(&fis); 466 } 467 return NULL; 468} 469 470// 4J Added function 471void DirectoryLevelStorage::clearOldPlayerFiles() 472{ 473 if(StorageManager.GetSaveDisabled() ) return; 474 475#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) 476 vector<FileEntry *> *playerFiles = m_saveFile->getValidPlayerDatFiles(); 477#else 478 vector<FileEntry *> *playerFiles = m_saveFile->getFilesWithPrefix( playerDir.getName() ); 479#endif 480 481 if( playerFiles != NULL ) 482 { 483#ifndef _FINAL_BUILD 484 if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_DistributableSave)) 485 { 486 for(unsigned int i = 0; i < playerFiles->size(); ++i ) 487 { 488 FileEntry *file = playerFiles->at(i); 489 wstring xuidStr = replaceAll( replaceAll(file->data.filename,playerDir.getName(),L""),L".dat",L""); 490#if defined(__PS3__) || defined(__ORBIS__) || defined(_DURANGO) 491 PlayerUID xuid(xuidStr); 492#else 493 PlayerUID xuid = _fromString<PlayerUID>(xuidStr); 494#endif 495 deleteMapFilesForPlayer(xuid); 496 m_saveFile->deleteFile( playerFiles->at(i) ); 497 } 498 } 499 else 500#endif 501 if( playerFiles->size() > MAX_PLAYER_DATA_SAVES ) 502 { 503 sort(playerFiles->begin(), playerFiles->end(), FileEntry::newestFirst ); 504 505 for(unsigned int i = MAX_PLAYER_DATA_SAVES; i < playerFiles->size(); ++i ) 506 { 507 FileEntry *file = playerFiles->at(i); 508 wstring xuidStr = replaceAll( replaceAll(file->data.filename,playerDir.getName(),L""),L".dat",L""); 509#if defined(__PS3__) || defined(__ORBIS__) || defined(_DURANGO) 510 PlayerUID xuid(xuidStr); 511#else 512 PlayerUID xuid = _fromString<PlayerUID>(xuidStr); 513#endif 514 deleteMapFilesForPlayer(xuid); 515 m_saveFile->deleteFile( playerFiles->at(i) ); 516 } 517 } 518 519 delete playerFiles; 520 } 521} 522 523PlayerIO *DirectoryLevelStorage::getPlayerIO() 524{ 525 return this; 526} 527 528void DirectoryLevelStorage::closeAll() 529{ 530} 531 532ConsoleSavePath DirectoryLevelStorage::getDataFile(const wstring& id) 533{ 534 return ConsoleSavePath( dataDir.getName() + id + L".dat" ); 535} 536 537wstring DirectoryLevelStorage::getLevelId() 538{ 539 return levelId; 540} 541 542void DirectoryLevelStorage::flushSaveFile(bool autosave) 543{ 544#ifndef _CONTENT_PACKAGE 545 if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_DistributableSave)) 546 { 547 // Delete gamerules files if it exists 548 ConsoleSavePath gameRulesFiles(GAME_RULE_SAVENAME); 549 if(m_saveFile->doesFileExist(gameRulesFiles)) 550 { 551 FileEntry *fe = m_saveFile->createFile(gameRulesFiles); 552 m_saveFile->deleteFile( fe ); 553 } 554 } 555#endif 556 m_saveFile->Flush(autosave); 557} 558 559// 4J Added 560void DirectoryLevelStorage::resetNetherPlayerPositions() 561{ 562 if(app.GetResetNether()) 563 { 564#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) 565 vector<FileEntry *> *playerFiles = m_saveFile->getValidPlayerDatFiles(); 566#else 567 vector<FileEntry *> *playerFiles = m_saveFile->getFilesWithPrefix( playerDir.getName() ); 568#endif 569 570 if( playerFiles != NULL ) 571 { 572 for( AUTO_VAR(it, playerFiles->begin()); it != playerFiles->end(); ++it) 573 { 574 FileEntry * realFile = *it; 575 ConsoleSaveFileInputStream fis = ConsoleSaveFileInputStream(m_saveFile, realFile); 576 CompoundTag *tag = NbtIo::readCompressed(&fis); 577 if (tag != NULL) 578 { 579 // If the player is in the nether, set their y position above the top of the nether 580 // This will force the player to be spawned in a valid position in the overworld when they are loaded 581 if(tag->contains(L"Dimension") && tag->getInt(L"Dimension") == LevelData::DIMENSION_NETHER && tag->contains(L"Pos")) 582 { 583 ListTag<DoubleTag> *pos = (ListTag<DoubleTag> *) tag->getList(L"Pos"); 584 pos->get(1)->data = DBL_MAX; 585 586 ConsoleSaveFileOutputStream fos = ConsoleSaveFileOutputStream( m_saveFile, realFile ); 587 NbtIo::writeCompressed(tag, &fos); 588 } 589 delete tag; 590 } 591 } 592 delete playerFiles; 593 } 594 } 595} 596 597int DirectoryLevelStorage::getAuxValueForMap(PlayerUID xuid, int dimension, int centreXC, int centreZC, int scale) 598{ 599 int mapId = -1; 600 bool foundMapping = false; 601 602#ifdef _LARGE_WORLDS 603 AUTO_VAR(it, m_playerMappings.find(xuid) ); 604 if(it != m_playerMappings.end()) 605 { 606 foundMapping = it->second.getMapping(mapId, centreXC, centreZC, dimension, scale); 607 } 608 609 if(!foundMapping) 610 { 611 for(unsigned int i = 0; i < m_usedMappings.length; ++i) 612 { 613 if(m_usedMappings[i] < 0xFF) 614 { 615 unsigned int offset = 0; 616 for(; offset < 8; ++offset) 617 { 618 if( !(m_usedMappings[i] & (1<<offset)) ) 619 { 620 break; 621 } 622 } 623 mapId = (i*8) + offset; 624 m_playerMappings[xuid].addMapping(mapId, centreXC, centreZC, dimension, scale); 625 m_usedMappings[i] |= (1<<offset); 626 break; 627 } 628 } 629 } 630#else 631 for(unsigned int i = 0; i < MAXIMUM_MAP_SAVE_DATA; ++i) 632 { 633 if(m_mapDataMappings.xuids[i] == xuid && m_mapDataMappings.getDimension(i) == dimension) 634 { 635 foundMapping = true; 636 mapId = i; 637 break; 638 } 639 if( mapId < 0 && m_mapDataMappings.xuids[i] == INVALID_XUID ) 640 { 641 mapId = i; 642 } 643 } 644 if( !foundMapping && mapId >= 0 && mapId < MAXIMUM_MAP_SAVE_DATA ) 645 { 646 m_mapDataMappings.setMapping(mapId, xuid, dimension); 647 m_saveableMapDataMappings.setMapping(mapId, xuid, dimension); 648 649 // If we had an old map file for a mapping that is no longer valid, delete it 650 std::wstring id = wstring( L"map_" ) + _toString(mapId); 651 ConsoleSavePath file = getDataFile(id); 652 653 if(m_saveFile->doesFileExist(file) ) 654 { 655 AUTO_VAR(it, find(m_mapFilesToDelete.begin(), m_mapFilesToDelete.end(), mapId)); 656 if(it != m_mapFilesToDelete.end()) m_mapFilesToDelete.erase(it); 657 658 m_saveFile->deleteFile( m_saveFile->createFile(file) ); 659 } 660 } 661#endif 662 return mapId; 663} 664 665void DirectoryLevelStorage::saveMapIdLookup() 666{ 667 if(StorageManager.GetSaveDisabled() ) return; 668 669#ifdef _LARGE_WORLDS 670 ConsoleSavePath file = getDataFile(L"largeMapDataMappings"); 671#else 672 ConsoleSavePath file = getDataFile(L"mapDataMappings"); 673#endif 674 675 if (!file.getName().empty()) 676 { 677 DWORD NumberOfBytesWritten; 678 FileEntry *fileEntry = m_saveFile->createFile(file); 679 m_saveFile->setFilePointer(fileEntry,0,NULL, FILE_BEGIN); 680 681#ifdef _LARGE_WORLDS 682 ByteArrayOutputStream baos; 683 DataOutputStream dos(&baos); 684 dos.writeInt(m_playerMappings.size()); 685 app.DebugPrintf("Saving %d mappings\n", m_playerMappings.size()); 686 for(AUTO_VAR(it,m_playerMappings.begin()); it != m_playerMappings.end(); ++it) 687 { 688#ifdef _WINDOWS64 689 app.DebugPrintf(" -- %d\n", it->first); 690#else 691 app.DebugPrintf(" -- %ls\n", it->first.toString().c_str()); 692#endif 693 dos.writePlayerUID(it->first); 694 it->second.writeMappings(&dos); 695 } 696 dos.write(m_usedMappings); 697 m_saveFile->writeFile( fileEntry, 698 baos.buf.data, // data buffer 699 baos.size(), // number of bytes to write 700 &NumberOfBytesWritten // number of bytes written 701 ); 702#else 703 m_saveFile->writeFile( fileEntry, 704 &m_saveableMapDataMappings, // data buffer 705 sizeof(MapDataMappings), // number of bytes to write 706 &NumberOfBytesWritten // number of bytes written 707 ); 708 assert( NumberOfBytesWritten == sizeof(MapDataMappings) ); 709#endif 710 } 711} 712 713void DirectoryLevelStorage::dontSaveMapMappingForPlayer(PlayerUID xuid) 714{ 715#ifdef _LARGE_WORLDS 716 AUTO_VAR(it, m_playerMappings.find(xuid) ); 717 if(it != m_playerMappings.end()) 718 { 719 for(AUTO_VAR(itMap, it->second.m_mappings.begin()); itMap != it->second.m_mappings.end(); ++itMap) 720 { 721 int index = itMap->second / 8; 722 int offset = itMap->second % 8; 723 m_usedMappings[index] &= ~(1<<offset); 724 } 725 m_playerMappings.erase(it); 726 } 727#else 728 for(unsigned int i = 0; i < MAXIMUM_MAP_SAVE_DATA; ++i) 729 { 730 if(m_saveableMapDataMappings.xuids[i] == xuid) 731 { 732 m_saveableMapDataMappings.setMapping(i,INVALID_XUID,0); 733 } 734 } 735#endif 736} 737 738void DirectoryLevelStorage::deleteMapFilesForPlayer(shared_ptr<Player> player) 739{ 740 PlayerUID playerXuid = player->getXuid(); 741 if(playerXuid != INVALID_XUID) deleteMapFilesForPlayer(playerXuid); 742} 743 744void DirectoryLevelStorage::deleteMapFilesForPlayer(PlayerUID xuid) 745{ 746#ifdef _LARGE_WORLDS 747 AUTO_VAR(it, m_playerMappings.find(xuid) ); 748 if(it != m_playerMappings.end()) 749 { 750 for(AUTO_VAR(itMap, it->second.m_mappings.begin()); itMap != it->second.m_mappings.end(); ++itMap) 751 { 752 std::wstring id = wstring( L"map_" ) + _toString(itMap->second); 753 ConsoleSavePath file = getDataFile(id); 754 755 if(m_saveFile->doesFileExist(file) ) 756 { 757 // If we can't actually delete this file, store the name so we can delete it later 758 if(StorageManager.GetSaveDisabled()) m_mapFilesToDelete.push_back(itMap->second); 759 else m_saveFile->deleteFile( m_saveFile->createFile(file) ); 760 } 761 762 int index = itMap->second / 8; 763 int offset = itMap->second % 8; 764 m_usedMappings[index] &= ~(1<<offset); 765 } 766 m_playerMappings.erase(it); 767 } 768#else 769 bool changed = false; 770 for(unsigned int i = 0; i < MAXIMUM_MAP_SAVE_DATA; ++i) 771 { 772 if(m_mapDataMappings.xuids[i] == xuid) 773 { 774 changed = true; 775 776 std::wstring id = wstring( L"map_" ) + _toString(i); 777 ConsoleSavePath file = getDataFile(id); 778 779 if(m_saveFile->doesFileExist(file) ) 780 { 781 // If we can't actually delete this file, store the name so we can delete it later 782 if(StorageManager.GetSaveDisabled()) m_mapFilesToDelete.push_back(i); 783 else m_saveFile->deleteFile( m_saveFile->createFile(file) ); 784 } 785 m_mapDataMappings.setMapping(i,INVALID_XUID,0); 786 m_saveableMapDataMappings.setMapping(i,INVALID_XUID,0); 787 break; 788 } 789 } 790#endif 791} 792 793void DirectoryLevelStorage::saveAllCachedData() 794{ 795 if(StorageManager.GetSaveDisabled() ) return; 796 797 // Save any files that were saved while saving was disabled 798 for(AUTO_VAR(it, m_cachedSaveData.begin()); it != m_cachedSaveData.end(); ++it) 799 { 800 ByteArrayOutputStream *bos = it->second; 801 802 ConsoleSavePath realFile = ConsoleSavePath( it->first ); 803 ConsoleSaveFileOutputStream fos = ConsoleSaveFileOutputStream( m_saveFile, realFile ); 804 805 app.DebugPrintf("Actually writing cached file %ls\n",it->first.c_str() ); 806 fos.write(bos->buf, 0, bos->size() ); 807 delete bos; 808 } 809 m_cachedSaveData.clear(); 810 811 for(AUTO_VAR(it, m_mapFilesToDelete.begin()); it != m_mapFilesToDelete.end(); ++it) 812 { 813 std::wstring id = wstring( L"map_" ) + _toString(*it); 814 ConsoleSavePath file = getDataFile(id); 815 if(m_saveFile->doesFileExist(file) ) 816 { 817 m_saveFile->deleteFile( m_saveFile->createFile(file) ); 818 } 819 } 820 m_mapFilesToDelete.clear(); 821}