refactor(Minecraft.World): Implement LCEMP changes.

This commit is contained in:
2026-07-13 00:14:53 +03:00
parent 3fce0538c5
commit 21e2add09a
64 changed files with 655 additions and 372 deletions
+135 -112
View File
@@ -180,120 +180,143 @@ HRESULT Compression::CompressRLE(void *pDestination, unsigned int *pDestSize, vo
return S_OK;
}
HRESULT Compression::DecompressLZXRLE(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize)
{
EnterCriticalSection(&rleDecompressLock);
// 4J Stu - Fix for #13676 - Crash: Crash while attempting to load a world after updating TU
// Some saves can have chunks that decompress into very large sizes, so I have doubled the size of this buffer
// Ideally we should be able to dynamically allocate the buffer if it's going to be too big, as most chunks
// only use 5% of this buffer
// 4J Stu - Changed this again to dynamically allocate a buffer if it's going to be too big
unsigned char *pucIn = NULL;
//const unsigned int staticRleSize = 1024*200;
//static unsigned char rleBuf[staticRleSize];
unsigned int rleSize = staticRleSize;
unsigned char *dynamicRleBuf = NULL;
if(*pDestSize > rleSize)
{
rleSize = *pDestSize;
dynamicRleBuf = new unsigned char[rleSize];
Decompress(dynamicRleBuf, &rleSize, pSource, SrcSize);
pucIn = (unsigned char *)dynamicRleBuf;
}
else
{
Decompress(rleDecompressBuf, &rleSize, pSource, SrcSize);
pucIn = (unsigned char *)rleDecompressBuf;
}
//unsigned char *pucIn = (unsigned char *)rleDecompressBuf;
unsigned char *pucEnd = pucIn + rleSize;
unsigned char *pucOut = (unsigned char *)pDestination;
while( pucIn != pucEnd )
{
unsigned char thisOne = *pucIn++;
if( thisOne == 255 )
{
unsigned int count = *pucIn++;
if( count < 3 )
{
count++;
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = 255;
}
}
else
{
count++;
unsigned char data = *pucIn++;
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = data;
}
}
}
else
{
*pucOut++ = thisOne;
}
}
*pDestSize = (unsigned int)(pucOut - (unsigned char *)pDestination);
// printf("Decompressed from %d to %d to %d\n",SrcSize,rleSize,*pDestSize);
if(dynamicRleBuf != NULL) delete [] dynamicRleBuf;
LeaveCriticalSection(&rleDecompressLock);
return S_OK;
HRESULT Compression::DecompressLZXRLE(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize)
{
EnterCriticalSection(&rleDecompressLock);
// 4J Stu - Fix for #13676 - Crash: Crash while attempting to load a world after updating TU
// Some saves can have chunks that decompress into very large sizes, so I have doubled the size of this buffer
// Ideally we should be able to dynamically allocate the buffer if it's going to be too big, as most chunks
// only use 5% of this buffer
// 4J Stu - Changed this again to dynamically allocate a buffer if it's going to be too big
unsigned char *pucIn = NULL;
//const unsigned int staticRleSize = 1024*200;
//static unsigned char rleBuf[staticRleSize];
unsigned int rleSize = staticRleSize;
unsigned char *dynamicRleBuf = NULL;
unsigned int safeRleSize = max(rleSize, *pDestSize);
const unsigned int MAX_RLE_ALLOC = 16 * 1024 * 1024; // 16 MB
if(safeRleSize > MAX_RLE_ALLOC)
{
LeaveCriticalSection(&rleDecompressLock);
*pDestSize = 0;
return E_FAIL;
}
if(safeRleSize > staticRleSize)
{
rleSize = safeRleSize;
dynamicRleBuf = new unsigned char[rleSize];
Decompress(dynamicRleBuf, &rleSize, pSource, SrcSize);
pucIn = (unsigned char *)dynamicRleBuf;
}
else
{
Decompress(rleDecompressBuf, &rleSize, pSource, SrcSize);
pucIn = (unsigned char *)rleDecompressBuf;
}
//unsigned char *pucIn = (unsigned char *)rleDecompressBuf;
unsigned char *pucEnd = pucIn + rleSize;
unsigned char *pucOut = (unsigned char *)pDestination;
unsigned char *pucOutEnd = pucOut + *pDestSize;
while( pucIn != pucEnd )
{
unsigned char thisOne = *pucIn++;
if( thisOne == 255 )
{
if( pucIn >= pucEnd ) break;
unsigned int count = *pucIn++;
if( count < 3 )
{
count++;
if( pucOut + count > pucOutEnd ) { pucOut = pucOutEnd; break; }
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = 255;
}
}
else
{
count++;
if( pucIn >= pucEnd ) break;
unsigned char data = *pucIn++;
if( pucOut + count > pucOutEnd ) { pucOut = pucOutEnd; break; }
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = data;
}
}
}
else
{
if( pucOut >= pucOutEnd ) break;
*pucOut++ = thisOne;
}
}
*pDestSize = (unsigned int)(pucOut - (unsigned char *)pDestination);
// printf("Decompressed from %d to %d to %d\n",SrcSize,rleSize,*pDestSize);
if(dynamicRleBuf != NULL) delete [] dynamicRleBuf;
LeaveCriticalSection(&rleDecompressLock);
return S_OK;
}
HRESULT Compression::DecompressRLE(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize)
{
EnterCriticalSection(&rleDecompressLock);
//unsigned char *pucIn = (unsigned char *)rleDecompressBuf;
unsigned char *pucIn = (unsigned char *)pSource;
unsigned char *pucEnd = pucIn + SrcSize;
unsigned char *pucOut = (unsigned char *)pDestination;
while( pucIn != pucEnd )
{
unsigned char thisOne = *pucIn++;
if( thisOne == 255 )
{
unsigned int count = *pucIn++;
if( count < 3 )
{
count++;
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = 255;
}
}
else
{
count++;
unsigned char data = *pucIn++;
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = data;
}
}
}
else
{
*pucOut++ = thisOne;
}
}
*pDestSize = (unsigned int)(pucOut - (unsigned char *)pDestination);
LeaveCriticalSection(&rleDecompressLock);
return S_OK;
HRESULT Compression::DecompressRLE(void *pDestination, unsigned int *pDestSize, void *pSource, unsigned int SrcSize)
{
EnterCriticalSection(&rleDecompressLock);
//unsigned char *pucIn = (unsigned char *)rleDecompressBuf;
unsigned char *pucIn = (unsigned char *)pSource;
unsigned char *pucEnd = pucIn + SrcSize;
unsigned char *pucOut = (unsigned char *)pDestination;
unsigned char *pucOutEnd = pucOut + *pDestSize;
while( pucIn != pucEnd )
{
unsigned char thisOne = *pucIn++;
if( thisOne == 255 )
{
if( pucIn >= pucEnd ) break;
unsigned int count = *pucIn++;
if( count < 3 )
{
count++;
if( pucOut + count > pucOutEnd ) { pucOut = pucOutEnd; break; }
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = 255;
}
}
else
{
count++;
if( pucIn >= pucEnd ) break;
unsigned char data = *pucIn++;
if( pucOut + count > pucOutEnd ) { pucOut = pucOutEnd; break; }
for( unsigned int i = 0; i < count; i++ )
{
*pucOut++ = data;
}
}
}
else
{
if( pucOut >= pucOutEnd ) break;
*pucOut++ = thisOne;
}
}
*pDestSize = (unsigned int)(pucOut - (unsigned char *)pDestination);
LeaveCriticalSection(&rleDecompressLock);
return S_OK;
}