Completely integrated the new axis ordering. Will update worlds accordingly

git-svn-id: http://mc-server.googlecode.com/svn/trunk@396 0a769ca7-a7f5-676a-18bf-c427514a06d6
master
faketruth 2012-03-10 22:10:15 +00:00
parent 4004129e11
commit f90a8928e7
3 changed files with 151 additions and 2 deletions

View File

@ -323,6 +323,12 @@ cWSSCompact::cPAKFile::cPAKFile(const AString & a_FileName, int a_LayerX, int a_
{
UpdateChunk1To2();
}
#if AXIS_ORDER == AXIS_ORDER_XZY
if( m_ChunkVersion == 2 ) // Convert chunks to version 3
{
UpdateChunk2To3();
}
#endif
}
@ -536,6 +542,144 @@ void cWSSCompact::cPAKFile::UpdateChunk1To2()
void cWSSCompact::cPAKFile::UpdateChunk2To3()
{
int Offset = 0;
AString NewDataContents;
int ChunksConverted = 0;
for (sChunkHeaders::iterator itr = m_ChunkHeaders.begin(); itr != m_ChunkHeaders.end(); ++itr)
{
sChunkHeader * Header = *itr;
if( ChunksConverted % 32 == 0 )
{
LOGINFO("Updating \"%s\" version 2 to version 3: %d %%", m_FileName.c_str(), (ChunksConverted * 100) / m_ChunkHeaders.size() );
}
ChunksConverted++;
AString Data;
int UncompressedSize = Header->m_UncompressedSize;
Data.assign(m_DataContents, Offset, Header->m_CompressedSize);
Offset += Header->m_CompressedSize;
// Crude data integrity check:
int ExpectedSize = (16*256*16)*2 + (16*256*16)/2; // For version 2
if (UncompressedSize < ExpectedSize)
{
LOGWARNING("Chunk [%d, %d] has too short decompressed data (%d bytes out of %d needed), erasing",
Header->m_ChunkX, Header->m_ChunkZ,
UncompressedSize, ExpectedSize
);
Offset += Header->m_CompressedSize;
continue;
}
// Decompress the data:
AString UncompressedData;
{
int errorcode = UncompressString(Data.data(), Data.size(), UncompressedData, UncompressedSize);
if (errorcode != Z_OK)
{
LOGERROR("Error %d decompressing data for chunk [%d, %d]",
errorcode,
Header->m_ChunkX, Header->m_ChunkZ
);
Offset += Header->m_CompressedSize;
continue;
}
}
if (UncompressedSize != (int)UncompressedData.size())
{
LOGWARNING("Uncompressed data size differs (exp %d bytes, got %d) for chunk [%d, %d]",
UncompressedSize, UncompressedData.size(),
Header->m_ChunkX, Header->m_ChunkZ
);
Offset += Header->m_CompressedSize;
continue;
}
std::auto_ptr<char> ConvertedData(new char[ ExpectedSize ]);
memset( ConvertedData.get(), 0, ExpectedSize );
// Cannot use cChunk::MakeIndex because it might change again?????????
// For compatibility, use what we know is current
#define MAKE_2_INDEX( x, y, z ) ( y + (z * 256) + (x * 256 * 16) )
#define MAKE_3_INDEX( x, y, z ) ( x + (z * 16) + (y * 16 * 16) )
unsigned int InChunkOffset = 0;
for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z ) for( int y = 0; y < 256; ++y ) // YZX Loop order is important, in 1.1 Y was first then Z then X
{
ConvertedData.get()[ MAKE_3_INDEX(x, y, z) ] = UncompressedData[InChunkOffset];
++InChunkOffset;
} // for y, z, x
unsigned int index2 = 0;
for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z ) for( int y = 0; y < 256; ++y )
{
ConvertedData.get()[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4) ) & 0x0f ) << ((x&1)*4);
++index2;
}
InChunkOffset += index2/2;
index2 = 0;
for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z ) for( int y = 0; y < 256; ++y )
{
ConvertedData.get()[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4) ) & 0x0f ) << ((x&1)*4);
++index2;
}
InChunkOffset += index2/2;
index2 = 0;
for( int x = 0; x < 16; ++x ) for( int z = 0; z < 16; ++z ) for( int y = 0; y < 256; ++y )
{
ConvertedData.get()[ InChunkOffset + MAKE_3_INDEX(x, y, z)/2 ] |= ( (UncompressedData[ InChunkOffset + index2/2 ] >> ((index2&1)*4) ) & 0x0f ) << ((x&1)*4);
++index2;
}
InChunkOffset += index2/2;
index2 = 0;
AString Converted(ConvertedData.get(), ExpectedSize);
// Add JSON data afterwards
if (UncompressedData.size() > InChunkOffset)
{
Converted.append( UncompressedData.begin() + InChunkOffset, UncompressedData.end() );
}
// Re-compress data
AString CompressedData;
{
int errorcode = CompressString(Converted.data(), Converted.size(), CompressedData);
if (errorcode != Z_OK)
{
LOGERROR("Error %d compressing data for chunk [%d, %d]",
errorcode,
Header->m_ChunkX, Header->m_ChunkZ
);
continue;
}
}
// Save into file's cache
Header->m_UncompressedSize = Converted.size();
Header->m_CompressedSize = CompressedData.size();
NewDataContents.append( CompressedData );
}
// Done converting
m_DataContents = NewDataContents;
m_ChunkVersion = 3;
SynchronizeFile();
LOGINFO("Updated \"%s\" version 2 to version 3", m_FileName.c_str() );
}
bool cWSSCompact::LoadChunkFromData(const cChunkCoords & a_Chunk, int & a_UncompressedSize, const AString & a_Data, cWorld * a_World)
{
// Crude data integrity check:

View File

@ -48,7 +48,11 @@ protected:
int GetLayerZ(void) const {return m_LayerZ; }
static const int PAK_VERSION = 1;
#if AXIS_ORDER == AXIS_ORDER_XZY
static const int CHUNK_VERSION = 3;
#elif AXIS_ORDER == AXIS_ORDER_YZX
static const int CHUNK_VERSION = 2;
#endif
protected:
AString m_FileName;
@ -67,7 +71,8 @@ protected:
bool SaveChunkToData(const cChunkCoords & a_Chunk, cWorld * a_World); // Saves the chunk to m_DataContents, updates headers and m_NumDirty
void SynchronizeFile(void); // Writes m_DataContents along with the headers to file, resets m_NumDirty
void UpdateChunk1To2(void);
void UpdateChunk1To2(void); // Height from 128 to 256
void UpdateChunk2To3(void); // Axis order from YZX to XZY
} ;
typedef std::list<cPAKFile *> cPAKFiles;

View File

@ -29,7 +29,7 @@ It will help us when the new chunk format comes out and we need to patch everyth
// Used to smoothly convert to new axis ordering. One will be removed when deemed stable.
#define AXIS_ORDER_YZX 1 // Original (1.1-)
#define AXIS_ORDER_XZY 2 // New (1.2+)
#define AXIS_ORDER AXIS_ORDER_YZX
#define AXIS_ORDER AXIS_ORDER_XZY