summaryrefslogblamecommitdiffstats
path: root/source/packets/cPacket_MapChunk.cpp
blob: 21c62da459703608bb64a11539096b6f380b6345 (plain) (tree)

























































































































































                                                                                                                                                                           

#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "cPacket_MapChunk.h"
#include "../ChunkDef.h"

#include "zlib.h"





cPacket_MapChunk::~cPacket_MapChunk()
{
	delete [] m_CompressedData;
}





cPacket_MapChunk::cPacket_MapChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const BLOCKTYPE * a_BlockData, const unsigned char * a_BiomeData)
{
	m_PacketID = E_MAP_CHUNK;

	m_PosX = a_ChunkX; // Chunk coordinates now, instead of block coordinates
	m_PosZ = a_ChunkZ;

	m_bContiguous = true;  // false = no biome data, true = with biome data
	m_BitMap1 = 0;
	m_BitMap2 = 0;

	m_UnusedInt = 0;

	
	const int BlockDataSize = (cChunkDef::Height / 16) * (4096 + 2048 + 2048 + 2048);
	const int BiomeDataSize = cChunkDef::Width * cChunkDef::Width;
	char AllData [ BlockDataSize + BiomeDataSize ];

#if AXIS_ORDER == AXIS_ORDER_YZX
	memset( AllData, 0, BlockDataSize );

	unsigned int iterator = 0;
	for ( int i = 0; i < (cChunkDef::Height / 16); ++i )
	{
		m_BitMap1 |= (1 << i); // This tells what chunks are sent. Use this to NOT send air only chunks (right now everything is sent)
		for ( int y = 0; y < 16; ++y ) for( int z = 0; z < 16; ++z ) for( int x = 0; x < 16; ++x )
		{
			int idx = cChunk::MakeIndex(x, y + i * 16, z);
			AllData[iterator] = a_BlockData[idx];
			++iterator;
		}  // for y, z, x
	}
	
	// Send block metadata:
	char * Meta = a_BlockData + cChunkDef::NumBlocks;
	for ( int i = 0; i < (cChunkDef::Height / 16); ++i )
	{
		for ( int y = 0; y < 16; ++y ) for( int z = 0; z < 16; ++z )
		{
			for ( int x = 0; x < 8; ++x )
			{
				AllData[iterator] = cChunk::GetNibble(Meta, x * 2 + 0, y + i * 16, z) | (cChunk::GetNibble(Meta, x * 2 + 1, y + i * 16, z ) << 4);
				++iterator;
			}  // for x
		}  // for y, z
	}
	
	// Send block light:
	char * Light = Meta + cChunkDef::NumBlocks / 2;
	for ( int i = 0; i < (cChunkDef::Height / 16); ++i )
	{
		for ( int y = 0; y < 16; ++y ) for( int z = 0; z < 16; ++z )
		{
			for ( int x = 0; x < 8; ++x )
			{
				AllData[iterator] = cChunk::GetNibble(Light, x * 2 + 0, y + i * 16, z ) | (cChunk::GetNibble(Light, x * 2 + 1, y + i * 16, z ) << 4);
				++iterator;
			}
		}
	}
	
	// Send sky light:
	char * SkyLight = Light + cChunkDef::NumBlocks / 2;
	for( int i = 0; i < (cChunkDef::Height/16); ++i )
	{
		for( int y = 0; y < 16; ++y ) for( int z = 0; z < 16; ++z )
		{
			for( int x = 0; x < 8; ++x )
			{
				AllData[iterator] = cChunk::GetNibble(SkyLight, x * 2 + 0, y + i * 16, z ) | (cChunk::GetNibble(SkyLight, x * 2 + 1, y + i * 16, z ) << 4);
				++iterator;
			}
		}
	}
	memcpy(AllData + BlockDataSize, a_BiomeData, BiomeDataSize);
#elif AXIS_ORDER == AXIS_ORDER_XZY
	for ( int i = 0; i < 16; ++i )
	{
		m_BitMap1 |= (1 << i);
	}
	memcpy(AllData, a_BlockData, BlockDataSize);
	memcpy(AllData + BlockDataSize, a_BiomeData, BiomeDataSize);
#endif  // AXIS_ORDER

	uLongf CompressedSize = compressBound( sizeof(AllData) );
	char * CompressedBlockData = new char[CompressedSize];

	compress2( (Bytef*)CompressedBlockData, &CompressedSize, (const Bytef*)AllData, sizeof(AllData), Z_DEFAULT_COMPRESSION);

	m_CompressedData = CompressedBlockData;
	m_CompressedSize = CompressedSize;
}





cPacket_MapChunk::cPacket_MapChunk( const cPacket_MapChunk & a_Copy )
{
	m_PacketID = E_MAP_CHUNK;

	m_PosX = a_Copy.m_PosX;
	m_PosZ = a_Copy.m_PosZ;
	m_bContiguous = a_Copy.m_bContiguous;
	m_BitMap1 = a_Copy.m_BitMap1;
	m_BitMap2 = a_Copy.m_BitMap2;

	m_CompressedSize = a_Copy.m_CompressedSize;
	m_CompressedData = new char[m_CompressedSize];
	memcpy( m_CompressedData, a_Copy.m_CompressedData, m_CompressedSize );
}





void cPacket_MapChunk::Serialize(AString & a_Data) const
{
	AppendByte   (a_Data, m_PacketID);

	AppendInteger(a_Data, m_PosX);
	AppendInteger(a_Data, m_PosZ);
	AppendBool   (a_Data, m_bContiguous);
	AppendShort  (a_Data, m_BitMap1);
	AppendShort  (a_Data, m_BitMap2);
	AppendInteger(a_Data, m_CompressedSize);
	AppendInteger(a_Data, m_UnusedInt);
	AppendData   (a_Data, m_CompressedData, m_CompressedSize);
}