aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.World/ChunkTilesUpdatePacket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Minecraft.World/ChunkTilesUpdatePacket.cpp')
-rw-r--r--Minecraft.World/ChunkTilesUpdatePacket.cpp173
1 files changed, 173 insertions, 0 deletions
diff --git a/Minecraft.World/ChunkTilesUpdatePacket.cpp b/Minecraft.World/ChunkTilesUpdatePacket.cpp
new file mode 100644
index 00000000..d90e6b2f
--- /dev/null
+++ b/Minecraft.World/ChunkTilesUpdatePacket.cpp
@@ -0,0 +1,173 @@
+#include "stdafx.h"
+#include <iostream>
+#include "InputOutputStream.h"
+#include "net.minecraft.world.level.h"
+#include "net.minecraft.world.level.chunk.h"
+#include "PacketListener.h"
+#include "ChunkTilesUpdatePacket.h"
+#include "Dimension.h"
+
+
+
+ChunkTilesUpdatePacket::~ChunkTilesUpdatePacket()
+{
+ delete [] blocks.data;
+ delete [] data.data;
+ delete [] positions.data;
+}
+
+ChunkTilesUpdatePacket::ChunkTilesUpdatePacket()
+{
+ shouldDelay = true;
+ xc = 0;
+ zc = 0;
+ count = 0;
+}
+
+ChunkTilesUpdatePacket::ChunkTilesUpdatePacket(int xc, int zc, shortArray positions, byte count, Level *level)
+{
+ shouldDelay = true;
+ this->xc = xc;
+ this->zc = zc;
+ this->count = count;
+ this->positions = shortArray(count);
+
+ this->blocks = byteArray(count);
+ this->data = byteArray(count);
+ LevelChunk *levelChunk = level->getChunk(xc, zc);
+ for (int i = 0; i < count; i++)
+ {
+ int x = (positions[i] >> 12) & 15;
+ int z = (positions[i] >> 8) & 15;
+ int y = (positions[i]) & 255;
+
+ this->positions[i] = positions[i];
+ blocks[i] = (byte) levelChunk->getTile(x, y, z);
+ data[i] = (byte) levelChunk->getData(x, y, z);
+ }
+ levelIdx = ( ( level->dimension->id == 0 ) ? 0 : ( (level->dimension->id == -1) ? 1 : 2 ) );
+}
+
+void ChunkTilesUpdatePacket::read(DataInputStream *dis) //throws IOException
+{
+ // 4J - changed format. See comments in write method.
+#ifdef _LARGE_WORLDS
+ xc = dis->readShort();
+ zc = dis->readShort();
+ xc = ( xc << 16 ) >> 16;
+ zc = ( zc << 16 ) >> 16;
+#else
+ xc = dis->read();
+ zc = dis->read();
+ xc = ( xc << 24 ) >> 24;
+ zc = ( zc << 24 ) >> 24;
+#endif
+
+ int countAndFlags = dis->readByte();
+ bool dataAllZero = (( countAndFlags & 0x80 ) == 0x80 );
+ levelIdx = ( countAndFlags >> 5 ) & 3;
+ count = countAndFlags & 0x1f;
+
+ positions = shortArray(count);
+ blocks = byteArray(count);
+ data = byteArray(count);
+
+ int currentBlockType = -1;
+ for( int i = 0; i < count; i++ )
+ {
+ int xzAndFlag = dis->readShort();
+ int y = dis->readByte();
+ positions[i] = (xzAndFlag & 0xff00) | (y & 0xff);
+ if( ( xzAndFlag & 0x0080 ) == 0x0080 )
+ {
+ currentBlockType = dis->read();
+ }
+ blocks[i] = currentBlockType;
+ if( !dataAllZero)
+ {
+ data[i] = dis->read();
+ }
+ else
+ {
+ data[i] = 0;
+ }
+ }
+}
+
+void ChunkTilesUpdatePacket::write(DataOutputStream *dos) //throws IOException
+{
+ // 4J - changed format to reduce size of these packets.
+#ifdef _LARGE_WORLDS
+ dos->writeShort(xc);
+ dos->writeShort(zc);
+#else
+ dos->write(xc);
+ dos->write(zc);
+#endif
+ // Determine if we've got any data elements that are non-zero - a large % of these packets set all data to zero, so we don't
+ // bother sending all those zeros in that case.
+ bool dataAllZero = true;
+ for( int i = 0; i < count; i++ )
+ {
+ if( data[i] ) dataAllZero = false;
+ }
+ int countAndFlags = count;
+ if( dataAllZero ) countAndFlags |= 0x80;
+ countAndFlags |= ( levelIdx << 5 );
+ dos->write(countAndFlags);
+ int lastBlockType = -1;
+ // Each block is represented by 15 bits of position, a flag to say whether the current block type is to change, and a possible data value.
+ // A large % of these packets set the same block type to a several positions, so no point resending the block type when not necessary.
+ for( int i = 0; i < count; i++ )
+ {
+ int xzAndFlag = positions[i] &0xff00;
+ int y = positions[i] & 0xff;
+ int thisBlockType = blocks[i];
+ if( thisBlockType != lastBlockType )
+ {
+ xzAndFlag |= 0x0080; // Use top bit of y as a flag, we only need 7 bits for that
+ dos->writeShort(xzAndFlag);
+ dos->write(y);
+ dos->write(thisBlockType);
+ lastBlockType = thisBlockType;
+ }
+ else
+ {
+ dos->writeShort(xzAndFlag);
+ dos->write(y);
+ }
+ if( !dataAllZero )
+ {
+ dos->write(data[i]);
+ }
+ }
+}
+
+void ChunkTilesUpdatePacket::handle(PacketListener *listener)
+{
+ listener->handleChunkTilesUpdate(shared_from_this());
+}
+
+int ChunkTilesUpdatePacket::getEstimatedSize()
+{
+ bool dataAllZero = true;
+ int lastBlockType = -1;
+ int blockTypeChanges = 0;
+ for( int i = 0; i < count; i++ )
+ {
+ if( data[i] ) dataAllZero = false;
+ int thisBlockType = blocks[i];
+ if( thisBlockType != lastBlockType )
+ {
+ blockTypeChanges++;
+ lastBlockType = thisBlockType;
+ }
+ }
+ int byteCount = 3 + 2 * count + blockTypeChanges;
+ if( !dataAllZero )
+ {
+ byteCount += count;
+ }
+
+ return byteCount;
+}