diff options
author | faketruth <faketruth@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2012-03-10 23:10:15 +0100 |
---|---|---|
committer | faketruth <faketruth@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2012-03-10 23:10:15 +0100 |
commit | f90a8928e78702b393ca2f688da6ca197eb94256 (patch) | |
tree | 1e797b311c2cd37e7d756d19701c27c9eb7b2765 | |
parent | Anvil support: compatible with both chunk orderings (diff) | |
download | cuberite-f90a8928e78702b393ca2f688da6ca197eb94256.tar cuberite-f90a8928e78702b393ca2f688da6ca197eb94256.tar.gz cuberite-f90a8928e78702b393ca2f688da6ca197eb94256.tar.bz2 cuberite-f90a8928e78702b393ca2f688da6ca197eb94256.tar.lz cuberite-f90a8928e78702b393ca2f688da6ca197eb94256.tar.xz cuberite-f90a8928e78702b393ca2f688da6ca197eb94256.tar.zst cuberite-f90a8928e78702b393ca2f688da6ca197eb94256.zip |
-rw-r--r-- | source/WSSCompact.cpp | 144 | ||||
-rw-r--r-- | source/WSSCompact.h | 7 | ||||
-rw-r--r-- | source/cChunk.h | 2 |
3 files changed, 151 insertions, 2 deletions
diff --git a/source/WSSCompact.cpp b/source/WSSCompact.cpp index 420ccba62..9515a1122 100644 --- a/source/WSSCompact.cpp +++ b/source/WSSCompact.cpp @@ -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:
diff --git a/source/WSSCompact.h b/source/WSSCompact.h index 968092611..cd753ce9c 100644 --- a/source/WSSCompact.h +++ b/source/WSSCompact.h @@ -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;
diff --git a/source/cChunk.h b/source/cChunk.h index 9a129ba31..55210a064 100644 --- a/source/cChunk.h +++ b/source/cChunk.h @@ -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
|