This code was not tested and breaks in Release builds, reverting to restore
functionality of the nightly. All in-game menus do not work and generating
a world crashes.
This reverts commit a9be52c41a.
622 lines
18 KiB
C++
622 lines
18 KiB
C++
#include "stdafx.h"
|
|
#include "File.h"
|
|
#include "InputOutputStream.h"
|
|
#include "net.minecraft.world.entity.h"
|
|
#include "net.minecraft.world.level.h"
|
|
#include "net.minecraft.world.level.chunk.h"
|
|
#include "net.minecraft.world.level.tile.entity.h"
|
|
#include "net.minecraft.world.level.storage.h"
|
|
#include "FileHeader.h"
|
|
#include "OldChunkStorage.h"
|
|
DWORD OldChunkStorage::tlsIdx = 0;
|
|
OldChunkStorage::ThreadStorage *OldChunkStorage::tlsDefault = NULL;
|
|
|
|
OldChunkStorage::ThreadStorage::ThreadStorage()
|
|
{
|
|
blockData = byteArray(Level::CHUNK_TILE_COUNT);
|
|
dataData = byteArray(Level::HALF_CHUNK_TILE_COUNT);
|
|
skyLightData = byteArray(Level::HALF_CHUNK_TILE_COUNT);
|
|
blockLightData = byteArray(Level::HALF_CHUNK_TILE_COUNT);
|
|
}
|
|
|
|
OldChunkStorage::ThreadStorage::~ThreadStorage()
|
|
{
|
|
delete [] blockData.data;
|
|
delete [] dataData.data;
|
|
delete [] skyLightData.data;
|
|
delete [] blockLightData.data;
|
|
}
|
|
|
|
void OldChunkStorage::CreateNewThreadStorage()
|
|
{
|
|
ThreadStorage *tls = new ThreadStorage();
|
|
if(tlsDefault == NULL )
|
|
{
|
|
tlsIdx = TlsAlloc();
|
|
tlsDefault = tls;
|
|
}
|
|
TlsSetValue(tlsIdx, tls);
|
|
}
|
|
|
|
void OldChunkStorage::UseDefaultThreadStorage()
|
|
{
|
|
TlsSetValue(tlsIdx, tlsDefault);
|
|
}
|
|
|
|
void OldChunkStorage::ReleaseThreadStorage()
|
|
{
|
|
ThreadStorage *tls = (ThreadStorage *)TlsGetValue(tlsIdx);
|
|
if( tls == tlsDefault ) return;
|
|
|
|
delete tls;
|
|
}
|
|
|
|
OldChunkStorage::OldChunkStorage(File dir, bool create)
|
|
{
|
|
this->dir = dir;
|
|
this->create = create;
|
|
}
|
|
|
|
File OldChunkStorage::getFile(int x, int z)
|
|
{
|
|
wchar_t name[MAX_PATH_SIZE];
|
|
wchar_t path1[MAX_PATH_SIZE];
|
|
wchar_t path2[MAX_PATH_SIZE];
|
|
|
|
wchar_t xRadix36[64];
|
|
wchar_t zRadix36[64];
|
|
#if ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ )
|
|
assert(0); // need a gcc verison of _itow ?
|
|
#else
|
|
_itow(x,xRadix36,36);
|
|
_itow(z,zRadix36,36);
|
|
swprintf(name,MAX_PATH_SIZE,L"c.%ls.%ls.dat",xRadix36,zRadix36);
|
|
_itow(x & 63,path1,36);
|
|
_itow(z & 63,path2,36);
|
|
#endif
|
|
//sprintf(file,"%s\\%s",dir,path1);
|
|
File file( dir, wstring( path1 ) );
|
|
if( !file.exists() )
|
|
{
|
|
if(create) file.mkdir();
|
|
else
|
|
{
|
|
return File(L"");
|
|
}
|
|
}
|
|
|
|
//strcat(file,"\\");
|
|
//strcat(file,path2);
|
|
file = File( file, wstring( path2 ) );
|
|
if( !file.exists() )
|
|
{
|
|
if(create) file.mkdir();
|
|
else
|
|
{
|
|
return File(L"");
|
|
}
|
|
}
|
|
|
|
//strcat(file,"\\");
|
|
//strcat(file,name);
|
|
//sprintf(file,"%s\\%s",file,name);
|
|
file = File( file, wstring( name ) );
|
|
if ( !file.exists() )
|
|
{
|
|
if (!create)
|
|
{
|
|
return File(L"");
|
|
}
|
|
}
|
|
return file;
|
|
}
|
|
|
|
LevelChunk *OldChunkStorage::load(Level *level, int x, int z)
|
|
{
|
|
File file = getFile(x, z);
|
|
if (!file.getPath().empty() && file.exists())
|
|
{
|
|
// 4J - removed try/catch
|
|
// try {
|
|
// System.out.println("Loading chunk "+x+", "+z);
|
|
FileInputStream fis = FileInputStream(file);
|
|
CompoundTag *tag = NbtIo::readCompressed(&fis);
|
|
if (!tag->contains(L"Level"))
|
|
{
|
|
char buf[256];
|
|
sprintf(buf,"Chunk file at %d, %d is missing level data, skipping\n",x,z);
|
|
app.DebugPrintf(buf);
|
|
return NULL;
|
|
}
|
|
if (!tag->getCompound(L"Level")->contains(L"Blocks"))
|
|
{
|
|
char buf[256];
|
|
sprintf(buf,"Chunk file at %d, %d is missing block data, skipping\n",x,z);
|
|
app.DebugPrintf(buf);
|
|
return NULL;
|
|
}
|
|
LevelChunk *levelChunk = OldChunkStorage::load(level, tag->getCompound(L"Level"));
|
|
if (!levelChunk->isAt(x, z))
|
|
{
|
|
char buf[256];
|
|
sprintf(buf,"Chunk fileat %d, %d is in the wrong location; relocating. Expected %d, %d, got %d, %d\n",
|
|
x, z, x, z, levelChunk->x, levelChunk->z);
|
|
app.DebugPrintf(buf);
|
|
tag->putInt(L"xPos", x);
|
|
tag->putInt(L"zPos", z);
|
|
levelChunk = OldChunkStorage::load(level, tag->getCompound(L"Level"));
|
|
}
|
|
|
|
return levelChunk;
|
|
// } catch (Exception e) {
|
|
// e.printStackTrace();
|
|
// }
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void OldChunkStorage::save(Level *level, LevelChunk *levelChunk)
|
|
{
|
|
level->checkSession();
|
|
File file = getFile(levelChunk->x, levelChunk->z);
|
|
if (file.exists())
|
|
{
|
|
LevelData *levelData = level->getLevelData();
|
|
levelData->setSizeOnDisk( levelData->getSizeOnDisk() - file.length() );
|
|
}
|
|
|
|
// 4J - removed try/catch
|
|
// try {
|
|
//char tmpFileName[MAX_PATH_SIZE];
|
|
//sprintf(tmpFileName,"%s\\%s",dir,"tmp_chunk.dat");
|
|
File tmpFile( dir, L"tmp_chunk.dat" );
|
|
// System.out.println("Saving chunk "+levelChunk.x+", "+levelChunk.z);
|
|
|
|
FileOutputStream fos = FileOutputStream(tmpFile);
|
|
CompoundTag *tag = new CompoundTag();
|
|
CompoundTag *levelData = new CompoundTag();
|
|
tag->put(L"Level", levelData);
|
|
OldChunkStorage::save(levelChunk, level, levelData);
|
|
NbtIo::writeCompressed(tag, &fos);
|
|
fos.close();
|
|
|
|
if (file.exists())
|
|
{
|
|
//DeleteFile(file);
|
|
file._delete();
|
|
}
|
|
//MoveFile(tmpFile,file);
|
|
tmpFile.renameTo( file );
|
|
|
|
LevelData *levelInfo = level->getLevelData();
|
|
levelInfo->setSizeOnDisk(levelInfo->getSizeOnDisk() + file.length() );
|
|
// } catch (Exception e) {
|
|
// e.printStackTrace();
|
|
// }
|
|
}
|
|
|
|
bool OldChunkStorage::saveEntities(LevelChunk *lc, Level *level, CompoundTag *tag)
|
|
{
|
|
// If we saved and it had no entities, and nothing has been added since skip this one
|
|
if(!lc->lastSaveHadEntities) return false;
|
|
|
|
lc->lastSaveHadEntities = false;
|
|
ListTag<CompoundTag> *entityTags = new ListTag<CompoundTag>();
|
|
|
|
#ifdef _ENTITIES_RW_SECTION
|
|
EnterCriticalRWSection(&lc->m_csEntities, true);
|
|
#else
|
|
EnterCriticalSection(&lc->m_csEntities);
|
|
#endif
|
|
for (int i = 0; i < lc->ENTITY_BLOCKS_LENGTH; i++)
|
|
{
|
|
for( auto& e : *lc->entityBlocks[i] )
|
|
{
|
|
lc->lastSaveHadEntities = true;
|
|
CompoundTag *teTag = new CompoundTag();
|
|
if ( e && e->save(teTag))
|
|
{
|
|
entityTags->add(teTag);
|
|
}
|
|
}
|
|
}
|
|
#ifdef _ENTITIES_RW_SECTION
|
|
LeaveCriticalRWSection(&lc->m_csEntities, true);
|
|
#else
|
|
LeaveCriticalSection(&lc->m_csEntities);
|
|
#endif
|
|
|
|
tag->put(L"Entities", entityTags);
|
|
|
|
return lc->lastSaveHadEntities;
|
|
}
|
|
|
|
void OldChunkStorage::save(LevelChunk *lc, Level *level, DataOutputStream *dos)
|
|
{
|
|
dos->writeShort(SAVE_FILE_VERSION_NUMBER);
|
|
dos->writeInt(lc->x);
|
|
dos->writeInt(lc->z);
|
|
dos->writeLong(level->getGameTime());
|
|
dos->writeLong(lc->inhabitedTime);
|
|
|
|
PIXBeginNamedEvent(0,"Getting block data");
|
|
lc->writeCompressedBlockData(dos);
|
|
PIXEndNamedEvent();
|
|
|
|
PIXBeginNamedEvent(0,"Getting data data");
|
|
lc->writeCompressedDataData(dos);
|
|
PIXEndNamedEvent();
|
|
|
|
PIXBeginNamedEvent(0,"Getting sky and block light data");
|
|
lc->writeCompressedSkyLightData(dos);
|
|
lc->writeCompressedBlockLightData(dos);
|
|
PIXEndNamedEvent();
|
|
|
|
dos->write(lc->heightmap);
|
|
dos->writeShort(lc->terrainPopulated);
|
|
dos->write(lc->getBiomes());
|
|
|
|
PIXBeginNamedEvent(0,"Saving entities");
|
|
CompoundTag *tag = new CompoundTag();
|
|
#ifndef SPLIT_SAVES
|
|
saveEntities(lc, level, tag);
|
|
#endif
|
|
|
|
PIXBeginNamedEvent(0,"Saving tile entities");
|
|
ListTag<CompoundTag> *tileEntityTags = new ListTag<CompoundTag>();
|
|
|
|
for(auto& it : lc->tileEntities)
|
|
{
|
|
shared_ptr<TileEntity> te = it.second;
|
|
CompoundTag *teTag = new CompoundTag();
|
|
te->save(teTag);
|
|
tileEntityTags->add(teTag);
|
|
}
|
|
tag->put(L"TileEntities", tileEntityTags);
|
|
PIXEndNamedEvent();
|
|
|
|
PIXBeginNamedEvent(0,"Saving tile tick data");
|
|
vector<TickNextTickData > *ticksInChunk = level->fetchTicksInChunk(lc, false);
|
|
if (ticksInChunk != NULL)
|
|
{
|
|
int64_t levelTime = level->getGameTime();
|
|
|
|
ListTag<CompoundTag> *tickTags = new ListTag<CompoundTag>();
|
|
for( int i = 0; i < ticksInChunk->size(); i++ )
|
|
{
|
|
TickNextTickData td = ticksInChunk->at(i);
|
|
CompoundTag *teTag = new CompoundTag();
|
|
teTag->putInt(L"i", td.tileId);
|
|
teTag->putInt(L"x", td.x);
|
|
teTag->putInt(L"y", td.y);
|
|
teTag->putInt(L"z", td.z);
|
|
teTag->putInt(L"t", (int) (td.m_delay - levelTime));
|
|
|
|
tickTags->add(teTag);
|
|
}
|
|
tag->put(L"TileTicks", tickTags);
|
|
}
|
|
delete ticksInChunk;
|
|
PIXEndNamedEvent();
|
|
|
|
NbtIo::write(tag,dos);
|
|
delete tag;
|
|
PIXEndNamedEvent();
|
|
}
|
|
|
|
void OldChunkStorage::save(LevelChunk *lc, Level *level, CompoundTag *tag)
|
|
{
|
|
level->checkSession();
|
|
tag->putInt(L"xPos", lc->x);
|
|
tag->putInt(L"zPos", lc->z);
|
|
tag->putLong(L"LastUpdate", level->getGameTime());
|
|
tag->putLong(L"InhabitedTime", lc->inhabitedTime);
|
|
// 4J - changes here for new storage. Now have static storage for getting lighting data for block, data, and sky & block lighting. This
|
|
// wasn't required in the original version as we could just reference the information in the level itself, but with our new storage system
|
|
// the full data doesn't normally exist & so getSkyLightData/getBlockLightData etc. need somewhere to output this data. Making this static so
|
|
// that we aren't dynamically allocating memory in the server thread when writing chunks as this causes serious stalling on the main thread.
|
|
// Will be fine so long as we only actually create tags for once chunk at a time.
|
|
|
|
// 4J Stu - As we now save on multiple threads, the static data has been moved to TLS
|
|
ThreadStorage *tls = (ThreadStorage *)TlsGetValue(tlsIdx);
|
|
|
|
PIXBeginNamedEvent(0,"Getting block data");
|
|
//static byteArray blockData = byteArray(32768);
|
|
lc->getBlockData(tls->blockData);
|
|
tag->putByteArray(L"Blocks", tls->blockData);
|
|
PIXEndNamedEvent();
|
|
|
|
PIXBeginNamedEvent(0,"Getting data data");
|
|
//static byteArray dataData = byteArray(16384);
|
|
lc->getDataData(tls->dataData);
|
|
tag->putByteArray(L"Data", tls->dataData);
|
|
PIXEndNamedEvent();
|
|
|
|
PIXBeginNamedEvent(0,"Getting sky and block light data");
|
|
//static byteArray skyLightData = byteArray(16384);
|
|
//static byteArray blockLightData = byteArray(16384);
|
|
lc->getSkyLightData(tls->skyLightData);
|
|
lc->getBlockLightData(tls->blockLightData);
|
|
tag->putByteArray(L"SkyLight", tls->skyLightData);
|
|
tag->putByteArray(L"BlockLight", tls->blockLightData);
|
|
PIXEndNamedEvent();
|
|
|
|
tag->putByteArray(L"HeightMap", lc->heightmap);
|
|
tag->putShort(L"TerrainPopulatedFlags", lc->terrainPopulated); // 4J - changed from "TerrainPopulated" to "TerrainPopulatedFlags" as now stores a bitfield, java stores a bool
|
|
tag->putByteArray(L"Biomes", lc->getBiomes());
|
|
|
|
PIXBeginNamedEvent(0,"Saving entities");
|
|
#ifndef SPLIT_SAVES
|
|
saveEntities(lc, level, tag);
|
|
#endif
|
|
|
|
PIXBeginNamedEvent(0,"Saving tile entities");
|
|
ListTag<CompoundTag> *tileEntityTags = new ListTag<CompoundTag>();
|
|
|
|
for(auto& it : lc->tileEntities)
|
|
{
|
|
shared_ptr<TileEntity> te = it.second;
|
|
CompoundTag *teTag = new CompoundTag();
|
|
te->save(teTag);
|
|
tileEntityTags->add(teTag);
|
|
}
|
|
tag->put(L"TileEntities", tileEntityTags);
|
|
PIXEndNamedEvent();
|
|
|
|
PIXBeginNamedEvent(0,"Saving tile tick data");
|
|
vector<TickNextTickData > *ticksInChunk = level->fetchTicksInChunk(lc, false);
|
|
if (ticksInChunk != NULL)
|
|
{
|
|
int64_t levelTime = level->getGameTime();
|
|
|
|
ListTag<CompoundTag> *tickTags = new ListTag<CompoundTag>();
|
|
for( int i = 0; i < ticksInChunk->size(); i++ )
|
|
{
|
|
TickNextTickData td = ticksInChunk->at(i);
|
|
CompoundTag *teTag = new CompoundTag();
|
|
teTag->putInt(L"i", td.tileId);
|
|
teTag->putInt(L"x", td.x);
|
|
teTag->putInt(L"y", td.y);
|
|
teTag->putInt(L"z", td.z);
|
|
teTag->putInt(L"t", (int) (td.m_delay - levelTime));
|
|
teTag->putInt(L"p", td.priorityTilt);
|
|
|
|
tickTags->add(teTag);
|
|
}
|
|
tag->put(L"TileTicks", tickTags);
|
|
}
|
|
delete ticksInChunk;
|
|
PIXEndNamedEvent();
|
|
PIXEndNamedEvent();
|
|
}
|
|
|
|
void OldChunkStorage::loadEntities(LevelChunk *lc, Level *level, CompoundTag *tag)
|
|
{
|
|
ListTag<CompoundTag> *entityTags = (ListTag<CompoundTag> *) tag->getList(L"Entities");
|
|
if (entityTags != NULL)
|
|
{
|
|
for (int i = 0; i < entityTags->size(); i++)
|
|
{
|
|
CompoundTag *teTag = entityTags->get(i);
|
|
shared_ptr<Entity> te = EntityIO::loadStatic(teTag, level);
|
|
lc->lastSaveHadEntities = true;
|
|
if (te != NULL)
|
|
{
|
|
lc->addEntity(te);
|
|
}
|
|
}
|
|
}
|
|
|
|
ListTag<CompoundTag> *tileEntityTags = (ListTag<CompoundTag> *) tag->getList(L"TileEntities");
|
|
if (tileEntityTags != NULL)
|
|
{
|
|
for (int i = 0; i < tileEntityTags->size(); i++)
|
|
{
|
|
CompoundTag *teTag = tileEntityTags->get(i);
|
|
shared_ptr<TileEntity> te = TileEntity::loadStatic(teTag);
|
|
if (te != NULL)
|
|
{
|
|
lc->addTileEntity(te);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LevelChunk *OldChunkStorage::load(Level *level, DataInputStream *dis)
|
|
{
|
|
PIXBeginNamedEvent(0,"Loading chunk");
|
|
short version = dis->readShort();
|
|
int x = dis->readInt();
|
|
int z = dis->readInt();
|
|
int time = dis->readLong();
|
|
|
|
LevelChunk *levelChunk = new LevelChunk(level, x, z);
|
|
|
|
if (version >= SAVE_FILE_VERSION_CHUNK_INHABITED_TIME)
|
|
{
|
|
levelChunk->inhabitedTime = dis->readLong();
|
|
}
|
|
|
|
levelChunk->readCompressedBlockData(dis);
|
|
levelChunk->readCompressedDataData(dis);
|
|
levelChunk->readCompressedSkyLightData(dis);
|
|
levelChunk->readCompressedBlockLightData(dis);
|
|
|
|
dis->readFully(levelChunk->heightmap);
|
|
|
|
levelChunk->terrainPopulated = dis->readShort();
|
|
// If all neighbours have been post-processed, then we should have done the post-post-processing now. Check that this is set as if it isn't then we won't be able
|
|
// to send network data for chunks, and we won't ever try and set it again as all the directional flags are now already set - should only be an issue for old maps
|
|
// before this flag was added.
|
|
if( ( levelChunk->terrainPopulated & LevelChunk::sTerrainPopulatedAllNeighbours ) == LevelChunk::sTerrainPopulatedAllNeighbours )
|
|
{
|
|
levelChunk->terrainPopulated |= LevelChunk::sTerrainPostPostProcessed;
|
|
}
|
|
|
|
#ifndef _CONTENT_PACKAGE
|
|
if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_EnableBiomeOverride))
|
|
{
|
|
// Read the biome data from the stream, but don't use it
|
|
byteArray dummyBiomes(levelChunk->biomes.length);
|
|
dis->readFully(dummyBiomes);
|
|
delete [] dummyBiomes.data;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
dis->readFully(levelChunk->biomes);
|
|
}
|
|
|
|
CompoundTag *tag = NbtIo::read(dis);
|
|
|
|
loadEntities(levelChunk, level, tag);
|
|
|
|
if (tag->contains(L"TileTicks"))
|
|
{
|
|
PIXBeginNamedEvent(0,"Loading TileTicks");
|
|
ListTag<CompoundTag> *tileTicks = (ListTag<CompoundTag> *) tag->getList(L"TileTicks");
|
|
|
|
if (tileTicks != NULL)
|
|
{
|
|
for (int i = 0; i < tileTicks->size(); i++)
|
|
{
|
|
CompoundTag *teTag = tileTicks->get(i);
|
|
|
|
level->forceAddTileTick(teTag->getInt(L"x"), teTag->getInt(L"y"), teTag->getInt(L"z"), teTag->getInt(L"i"), teTag->getInt(L"t"), teTag->getInt(L"p"));
|
|
}
|
|
}
|
|
PIXEndNamedEvent();
|
|
}
|
|
|
|
delete tag;
|
|
|
|
PIXEndNamedEvent();
|
|
|
|
return levelChunk;
|
|
}
|
|
|
|
LevelChunk *OldChunkStorage::load(Level *level, CompoundTag *tag)
|
|
{
|
|
int x = tag->getInt(L"xPos");
|
|
int z = tag->getInt(L"zPos");
|
|
|
|
LevelChunk *levelChunk = new LevelChunk(level, x, z);
|
|
// 4J - the original code uses the data in the tag directly, but this is now just used as a source when creating the compressed data, so
|
|
// we need to free up the data in the tag once we are done
|
|
levelChunk->setBlockData(tag->getByteArray(L"Blocks"));
|
|
delete [] tag->getByteArray(L"Blocks").data;
|
|
// levelChunk->blocks = tag->getByteArray(L"Blocks");
|
|
|
|
// 4J - the original code uses the data in the tag directly, but this is now just used as a source when creating the compressed data, so
|
|
// we need to free up the data in the tag once we are done
|
|
levelChunk->setDataData(tag->getByteArray(L"Data"));
|
|
delete [] tag->getByteArray(L"Data").data;
|
|
|
|
// 4J - changed to use our new methods for accessing lighting
|
|
levelChunk->setSkyLightData(tag->getByteArray(L"SkyLight"));
|
|
levelChunk->setBlockLightData(tag->getByteArray(L"BlockLight"));
|
|
|
|
// In the original code (commented out below) constructing DataLayers from these arrays uses the data directly and so it doesn't need deleted. The new
|
|
// setSkyLightData/setBlockLightData take a copy of the data so we need to delete the local one now
|
|
delete [] tag->getByteArray(L"SkyLight").data;
|
|
delete [] tag->getByteArray(L"BlockLight").data;
|
|
|
|
// levelChunk->skyLight = new DataLayer(tag->getByteArray(L"SkyLight"), level->depthBits);
|
|
// levelChunk->blockLight = new DataLayer(tag->getByteArray(L"BlockLight"), level->depthBits);
|
|
|
|
delete [] levelChunk->heightmap.data;
|
|
levelChunk->heightmap = tag->getByteArray(L"HeightMap");
|
|
// 4J - TerrainPopulated was a bool (java), then changed to be a byte bitfield, then replaced with TerrainPopulatedShort to store a wider bitfield
|
|
if( tag->get(L"TerrainPopulated") )
|
|
{
|
|
// Java bool type or byte bitfield
|
|
levelChunk->terrainPopulated = tag->getByte(L"TerrainPopulated");
|
|
if( levelChunk->terrainPopulated >= 1 ) levelChunk->terrainPopulated = LevelChunk::sTerrainPopulatedAllNeighbours | LevelChunk::sTerrainPostPostProcessed; // Convert from old bool type to new bitfield
|
|
}
|
|
else
|
|
{
|
|
// New style short
|
|
levelChunk->terrainPopulated = tag->getShort(L"TerrainPopulatedFlags");
|
|
// If all neighbours have been post-processed, then we should have done the post-post-processing now. Check that this is set as if it isn't then we won't be able
|
|
// to send network data for chunks, and we won't ever try and set it again as all the directional flags are now already set - should only be an issue for old maps
|
|
// before this flag was added.
|
|
if( ( levelChunk->terrainPopulated & LevelChunk::sTerrainPopulatedAllNeighbours ) == LevelChunk::sTerrainPopulatedAllNeighbours )
|
|
{
|
|
levelChunk->terrainPopulated |= LevelChunk::sTerrainPostPostProcessed;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
// 4J - removed - we shouldn't need this any more
|
|
if (!levelChunk->data->isValid())
|
|
{
|
|
levelChunk->data = new DataLayer(LevelChunk::BLOCKS_LENGTH, level->depthBits); // 4J - BLOCKS_LENGTH was levelChunk->blocks.length
|
|
}
|
|
#endif
|
|
|
|
// 4J removed - we shouldn't need this any more
|
|
#if 0
|
|
if (levelChunk->heightmap.data == NULL || !levelChunk->skyLight->isValid())
|
|
{
|
|
static int chunksUpdated = 0;
|
|
delete [] levelChunk->heightmap.data;
|
|
levelChunk->heightmap = byteArray(16 * 16);
|
|
delete levelChunk->skyLight;
|
|
levelChunk->skyLight = new DataLayer(levelChunk->blocks.length, level->depthBits);
|
|
levelChunk->recalcHeightmap();
|
|
}
|
|
|
|
if (!levelChunk->blockLight->isValid())
|
|
{
|
|
delete levelChunk->blockLight;
|
|
levelChunk->blockLight = new DataLayer(levelChunk->blocks.length, level->depthBits);
|
|
levelChunk->recalcBlockLights();
|
|
}
|
|
#endif
|
|
|
|
#ifndef _CONTENT_PACKAGE
|
|
if(app.DebugSettingsOn() && app.GetGameSettingsDebugMask(ProfileManager.GetPrimaryPad())&(1L<<eDebugSetting_EnableBiomeOverride))
|
|
{
|
|
// Do nothing
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
if (tag->contains(L"Biomes"))
|
|
{
|
|
levelChunk->setBiomes(tag->getByteArray(L"Biomes"));
|
|
}
|
|
}
|
|
|
|
loadEntities(levelChunk, level, tag);
|
|
|
|
if (tag->contains(L"TileTicks"))
|
|
{
|
|
ListTag<CompoundTag> *tileTicks = (ListTag<CompoundTag> *) tag->getList(L"TileTicks");
|
|
|
|
if (tileTicks != NULL)
|
|
{
|
|
for (int i = 0; i < tileTicks->size(); i++)
|
|
{
|
|
CompoundTag *teTag = tileTicks->get(i);
|
|
|
|
level->forceAddTileTick(teTag->getInt(L"x"), teTag->getInt(L"y"), teTag->getInt(L"z"), teTag->getInt(L"i"), teTag->getInt(L"t"), teTag->getInt(L"p"));
|
|
}
|
|
}
|
|
}
|
|
|
|
return levelChunk;
|
|
}
|
|
|
|
void OldChunkStorage::tick()
|
|
{
|
|
}
|
|
|
|
void OldChunkStorage::flush()
|
|
{
|
|
}
|
|
|
|
void OldChunkStorage::saveEntities(Level *level, LevelChunk *levelChunk)
|
|
{
|
|
}
|