aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.World/BlockRegionUpdatePacket.cpp
diff options
context:
space:
mode:
authordaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
committerdaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
commitb691c43c44ff180d10e7d4a9afc83b98551ff586 (patch)
tree3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.World/BlockRegionUpdatePacket.cpp
parentdef8cb415354ac390b7e89052a50605285f1aca9 (diff)
Initial commit
Diffstat (limited to 'Minecraft.World/BlockRegionUpdatePacket.cpp')
-rw-r--r--Minecraft.World/BlockRegionUpdatePacket.cpp157
1 files changed, 157 insertions, 0 deletions
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 <iostream>
+#include <exception>
+#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;
+}
+