From b691c43c44ff180d10e7d4a9afc83b98551ff586 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Sun, 1 Mar 2026 12:16:08 +0800 Subject: Initial commit --- Minecraft.World/BlockRegionUpdatePacket.cpp | 157 ++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 Minecraft.World/BlockRegionUpdatePacket.cpp (limited to 'Minecraft.World/BlockRegionUpdatePacket.cpp') diff --git a/Minecraft.World/BlockRegionUpdatePacket.cpp b/Minecraft.World/BlockRegionUpdatePacket.cpp new file mode 100644 index 00000000..d85321a5 --- /dev/null +++ b/Minecraft.World/BlockRegionUpdatePacket.cpp @@ -0,0 +1,157 @@ +#include "stdafx.h" +#include +#include +#include "InputOutputStream.h" +#include "net.minecraft.world.level.h" +#include "compression.h" +#include "PacketListener.h" +#include "BlockRegionUpdatePacket.h" +#include "LevelChunk.h" +#include "DataLayer.h" +#include "Dimension.h" + + + +BlockRegionUpdatePacket::~BlockRegionUpdatePacket() +{ + delete [] buffer.data; +} + +BlockRegionUpdatePacket::BlockRegionUpdatePacket() +{ + shouldDelay = true; + x = 0; + y = 0; + z = 0; + xs = 0; + ys = 0; + zs = 0; + bIsFullChunk = false; +} + +BlockRegionUpdatePacket::BlockRegionUpdatePacket(int x, int y, int z, int xs, int ys, int zs, Level *level) +{ + + shouldDelay = true; + this->x = x; + this->y = y; + this->z = z; + this->xs = xs; + this->ys = ys; + this->zs = zs; + bIsFullChunk = false; + levelIdx = ( ( level->dimension->id == 0 ) ? 0 : ( (level->dimension->id == -1) ? 1 : 2 ) ); + + // 4J - if we are compressing a full chunk, re-order the blocks so that they compress better + // TODO - we should be using compressed data directly here rather than decompressing first and then recompressing... + byteArray rawBuffer; + + if( xs == 16 && ys == Level::maxBuildHeight && zs == 16 && ( ( x & 15 ) == 0 ) && ( y == 0 ) && ( ( z & 15 ) == 0 ) ) + { + bIsFullChunk = true; + + LevelChunk *lc = level->getChunkAt(x,z); + rawBuffer = lc->getReorderedBlocksAndData(x&0xF, y, z&0xF, xs, this->ys, zs); + } + else + { + MemSect(50); + rawBuffer = level->getBlocksAndData(x, y, z, xs, ys, zs, false); + MemSect(0); + } + + if(rawBuffer.length == 0) + { + size = 0; + buffer = byteArray(); + } + else + { + // We don't know how this will compress - just make a fixed length buffer to initially decompress into + // Some small sets of blocks can end up compressing into something bigger than their source + unsigned char *ucTemp = new unsigned char[(256 * 16 * 16 * 5)/2]; + unsigned int inputSize = (256 * 16 * 16 * 5)/2; + + Compression::getCompression()->CompressLZXRLE(ucTemp, &inputSize, rawBuffer.data, (unsigned int) rawBuffer.length); + //app.DebugPrintf("Chunk (%d,%d) compressed from %d to size %d\n", x>>4, z>>4, rawBuffer.length, inputSize); + unsigned char *ucTemp2 = new unsigned char[inputSize]; + memcpy(ucTemp2,ucTemp,inputSize); + delete [] ucTemp; + buffer = byteArray(ucTemp2,inputSize); + delete [] rawBuffer.data; + size = inputSize; + } +} + +void BlockRegionUpdatePacket::read(DataInputStream *dis) //throws IOException +{ + bIsFullChunk = dis->readBoolean(); + x = dis->readInt(); + y = dis->readShort(); + z = dis->readInt(); + xs = dis->read() + 1; + ys = dis->read() + 1; + zs = dis->read() + 1; + + size = dis->readInt(); + levelIdx = ( size >> 30 ) & 3; + size &= 0x3fffffff; + + if(size == 0) + { + buffer = byteArray(); + } + else + { + byteArray compressedBuffer(size); + bool success = dis->readFully(compressedBuffer); + + int bufferSize = xs * ys * zs * 5/2; + // Add the size of the biome data if it's a full chunk + if(bIsFullChunk) bufferSize += (16*16); + buffer = byteArray(bufferSize); + unsigned int outputSize = buffer.length; + + if( success ) + { + Compression::getCompression()->DecompressLZXRLE( buffer.data, &outputSize, compressedBuffer.data, size); + } + else + { + app.DebugPrintf("Not decompressing packet that wasn't fully read\n"); + } + + // printf("Block (%d %d %d), (%d %d %d) coming in decomp from %d to %d\n",x,y,z,xs,ys,zs,size,outputSize); + + + delete [] compressedBuffer.data; + assert(buffer.length == outputSize); + } +} + +void BlockRegionUpdatePacket::write(DataOutputStream *dos) // throws IOException +{ + dos->writeBoolean(bIsFullChunk); + dos->writeInt(x); + dos->writeShort(y); + dos->writeInt(z); + dos->write(xs - 1); + dos->write(ys - 1); + dos->write(zs - 1); + + int sizeAndLevel = size; + sizeAndLevel |= ( levelIdx << 30 ); + dos->writeInt(sizeAndLevel); + dos->write(buffer, 0, size); +} + +void BlockRegionUpdatePacket::handle(PacketListener *listener) +{ + listener->handleBlockRegionUpdate(shared_from_this()); +} + +int BlockRegionUpdatePacket::getEstimatedSize() +{ + return 17 + size; +} + -- cgit v1.2.3