diff options
Diffstat (limited to 'Minecraft.World/ChunkTilesUpdatePacket.cpp')
| -rw-r--r-- | Minecraft.World/ChunkTilesUpdatePacket.cpp | 173 |
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; +} |
