diff options
author | admin@omencraft.com <admin@omencraft.com@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2011-11-04 21:13:10 +0100 |
---|---|---|
committer | admin@omencraft.com <admin@omencraft.com@0a769ca7-a7f5-676a-18bf-c427514a06d6> | 2011-11-04 21:13:10 +0100 |
commit | c10ba99d155ec0f1b0b735d3651d3b78304c6b82 (patch) | |
tree | d697ccc211edf74c7dbc88f5c8bc02551b0290c2 /converter/source/cNBTData.cpp | |
parent | Updated denotch map converter. Compiled with zlib that MCServr uses to remove the lag spike problem caused when reading map files using a different compression. Remade makefile and cleaned up code considerably. (diff) | |
download | cuberite-c10ba99d155ec0f1b0b735d3651d3b78304c6b82.tar cuberite-c10ba99d155ec0f1b0b735d3651d3b78304c6b82.tar.gz cuberite-c10ba99d155ec0f1b0b735d3651d3b78304c6b82.tar.bz2 cuberite-c10ba99d155ec0f1b0b735d3651d3b78304c6b82.tar.lz cuberite-c10ba99d155ec0f1b0b735d3651d3b78304c6b82.tar.xz cuberite-c10ba99d155ec0f1b0b735d3651d3b78304c6b82.tar.zst cuberite-c10ba99d155ec0f1b0b735d3651d3b78304c6b82.zip |
Diffstat (limited to '')
-rw-r--r-- | converter/source/cNBTData.cpp | 922 |
1 files changed, 922 insertions, 0 deletions
diff --git a/converter/source/cNBTData.cpp b/converter/source/cNBTData.cpp new file mode 100644 index 000000000..556960732 --- /dev/null +++ b/converter/source/cNBTData.cpp @@ -0,0 +1,922 @@ +#include "cNBTData.h" +#include <string> // memcpy +#include <stdio.h> +#include "zlib.h" +#include <assert.h> +#include <iostream> + +#ifndef _WIN32 +#include <cstring> +#include <netinet/in.h> +#endif + +#ifdef _WIN32 +#include <WinSock2.h> +#endif + +cNBTData::~cNBTData() +{ + // TODO: Delete all compounds and stuff in it + Clear(); +} + +cNBTData::cNBTData( char* a_Buffer, unsigned int a_BufferSize ) + : cNBTCompound( 0 ) +{ + m_NumUnnamedElements = 0; + for(int i = 0; i < TAG_NumTags; i++) + { + m_ParseFunctions[i] = 0; + } + m_ParseFunctions[TAG_Byte] = &cNBTData::ParseByte; + m_ParseFunctions[TAG_Short] = &cNBTData::ParseShort; + m_ParseFunctions[TAG_Int] = &cNBTData::ParseInt; + m_ParseFunctions[TAG_Long] = &cNBTData::ParseLong; + m_ParseFunctions[TAG_Double] = &cNBTData::ParseDouble; + m_ParseFunctions[TAG_Float] = &cNBTData::ParseFloat; + m_ParseFunctions[TAG_String] = &cNBTData::ParseString; + m_ParseFunctions[TAG_List] = &cNBTData::ParseList; + m_ParseFunctions[TAG_Compound] = &cNBTData::ParseCompound; + m_ParseFunctions[TAG_ByteArray] = &cNBTData::ParseByteArray; + + + m_Buffer = a_Buffer; + m_BufferSize = a_BufferSize; + m_Index = 0; + + tm = false; //tm to true will print more information for test mode + if (m_BufferSize == 82659) { +// tm = true; + } + + m_CurrentCompound = this; + + m_bDecompressed = true; +} + +bool cNBTData::OpenCompound( std::string a_Name ) +{ + cNBTCompound* Compound = GetCompound( a_Name ); + if( Compound ) + { + m_CurrentCompound = Compound; + return true; + } + printf("WARNING: Could not open NBT Compound %s\n", a_Name.c_str() ); + return false; +} + +bool cNBTData::CloseCompound() +{ + if( m_CurrentCompound->GetParentCompound() ) + { + m_CurrentCompound = m_CurrentCompound->GetParentCompound(); + return true; + } + printf("WARNING: Could not close NBT Compound, already at root!\n" ); + return false; +} + +bool cNBTCompound::OpenList( std::string a_Name ) +{ + if( GetList( a_Name ) ) + { + m_CurrentList = GetList( a_Name ); + return true; + } + printf("WARNING: Could not open NBT List %s\n", a_Name.c_str() ); + return false; +} + +bool cNBTCompound::CloseList() +{ + if( m_CurrentList ) + { + m_CurrentList = m_CurrentList->GetParentList(); + return true; + } + printf("WARNING: Could not close NBT List, no list open!\n" ); + return false; +} + +bool cNBTData::OpenList( std::string a_Name ) +{ + return m_CurrentCompound->OpenList( a_Name ); +} + +bool cNBTData::CloseList() +{ + return m_CurrentCompound->CloseList(); +} + +void cNBTData::Compress() +{ + //printf("Before Compress size: %i\n", m_BufferSize );//re + const int MAXNBTSIZE = 1024 * 1024 * 120; + + int ret; + unsigned have; + z_stream strm; + unsigned char* Compressed = new unsigned char[MAXNBTSIZE]; + + /* allocate deflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = m_BufferSize; + strm.avail_out = MAXNBTSIZE; + strm.next_in =(Bytef*)m_Buffer; + strm.next_out = Compressed; + strm.total_in = 0; + strm.total_out = 0; + ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15+MAX_WBITS, 8, Z_DEFAULT_STRATEGY); + if (ret != Z_OK) + { + printf("deflateInit2 returned NOT OK\n"); + return; + } + + + + /* run deflate() on input until output buffer not full, finish + compression if all of source has been read in */ + + ret = deflate(&strm, Z_FULL_FLUSH); /* no bad return value */ + if( ret != Z_OK ) + { + printf("WARNING: deflate returned NOT OK\n"); + } + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + have = strm.total_out; + + assert(strm.avail_in == 0); /* all input will be used */ + + if( ret != Z_STREAM_END ) + { + //printf("WARNING: Compressing didn't go to end of stream\n");//re + } + + if(m_Buffer) + { + delete [] m_Buffer; + m_Buffer = 0; + } + + //printf("Compressed size: %i\n", have );//re + + m_BufferSize = have; + m_Buffer = new char[ m_BufferSize ]; + memcpy( m_Buffer, Compressed, m_BufferSize ); + delete Compressed; + + /* clean up and return */ + deflateEnd(&strm); + m_bDecompressed = false; + return; +} + +bool cNBTData::Decompress() +{ + if( m_bDecompressed ) + { + printf("WARNING: Decompress called, while it has already been decompressed\n"); + return false; + } + if( m_BufferSize == 0 ) + { + printf("WARNING: Decompress called, with m_BufferSize of 0\n"); + return false; + } + + //printf("Before Decompress size: %i\n", m_BufferSize );//re + + const int MAXNBTSIZE = 1024 * 1024 * 120 ; + + int ret; + z_stream strm; + unsigned char* out = new unsigned char[MAXNBTSIZE]; + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = Z_NULL; + strm.next_in = Z_NULL; + strm.avail_in = m_BufferSize; + strm.avail_out = Z_NULL; + strm.next_in = (Bytef*)m_Buffer; + strm.next_out = Z_NULL; + strm.avail_out = MAXNBTSIZE; + strm.next_out = out; + strm.total_in = 0; + strm.total_out = 0; + + ret = inflateInit2(&strm, 16+MAX_WBITS); + if (ret != Z_OK) + { + printf("inflateInit2 returned NOT OK\n"); + delete out; + return false; + } + + if( (ret = inflate(&strm, Z_NO_FLUSH)) != Z_STREAM_END) + { + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + printf("ret != Z_STREAM_END\n"); + } + unsigned UncompressedSize = strm.total_out; //MAXNBTSIZE - strm.avail_out; + + m_Buffer = new char[ UncompressedSize ]; + memcpy( m_Buffer, out, UncompressedSize ); + m_BufferSize = UncompressedSize; + + inflateEnd(&strm); + delete [] out; + + if( ret != Z_STREAM_END ) + { + printf("WARNING: NBT Data received was too big! (More than %i bytes)\n", MAXNBTSIZE); + } + + //printf("Decompressed Size: %i\n", UncompressedSize );//re + m_bDecompressed = true; + return (ret == Z_STREAM_END) ? true : false; +} + +void cNBTCompound::AppendShort( std::string & a_Buffer, short a_Value ) +{ + a_Buffer.push_back( (char)((a_Value>>8)&0xff) ); + a_Buffer.push_back( (char)((a_Value)&0xff) ); +} + +void cNBTCompound::AppendInteger( std::string & a_Buffer, int a_Value ) +{ + int NetVal = htonl( a_Value ); + a_Buffer.append( (char*)&NetVal, sizeof( int ) ); +} + +void cNBTCompound::Serialize(std::string & a_Buffer) +{ + //printf("cNBTCompound::Serialize()\n");//re + for( CompoundMap::iterator itr = m_Compounds.begin(); itr != m_Compounds.end(); itr++ ) + { + if( itr->second == 0 ) continue; + a_Buffer.push_back( TAG_Compound ); + AppendShort( a_Buffer, (short)itr->first.size() ); + if( itr->first.size() > 0 ) + { + a_Buffer.append( itr->first.c_str(), itr->first.size() ); + } + itr->second->Serialize( a_Buffer ); + a_Buffer.push_back( TAG_End ); + } + + for( ListMap::iterator itr = m_Lists.begin(); itr != m_Lists.end(); itr++ ) + { + if( itr->second == 0 ) continue; + a_Buffer.push_back( TAG_List ); + AppendShort( a_Buffer, (short)itr->first.size() ); + if( itr->first.size() > 0 ) + { + a_Buffer.append( itr->first.c_str(), itr->first.size() ); + } + a_Buffer.push_back( (char)itr->second->GetType() ); + AppendInteger( a_Buffer, itr->second->GetSize() ); + itr->second->Serialize( a_Buffer ); + } + + for( IntegerMap::iterator itr = m_Integers.begin(); itr != m_Integers.end(); itr++ ) + { + a_Buffer.push_back( TAG_Int ); + AppendShort( a_Buffer, (short)itr->first.size() ); + if( itr->first.size() > 0 ) + { + a_Buffer.append( itr->first.c_str(), itr->first.size() ); + } + AppendInteger( a_Buffer, itr->second ); + } + + for( ShortMap::iterator itr = m_Shorts.begin(); itr != m_Shorts.end(); itr++ ) + { + a_Buffer.push_back( TAG_Short ); + AppendShort( a_Buffer, (short)itr->first.size() ); + if( itr->first.size() > 0 ) + { + a_Buffer.append( itr->first.c_str(), itr->first.size() ); + } + AppendShort( a_Buffer, itr->second ); + } + + for( ByteMap::iterator itr = m_Bytes.begin(); itr != m_Bytes.end(); itr++ ) + { + a_Buffer.push_back( TAG_Byte ); + AppendShort( a_Buffer, (short)itr->first.size() ); + if( itr->first.size() > 0 ) + { + a_Buffer.append( itr->first.c_str(), itr->first.size() ); + } + a_Buffer.push_back( itr->second ); + } + + for( DoubleMap::iterator itr = m_Doubles.begin(); itr != m_Doubles.end(); itr++ ) + { + a_Buffer.push_back( TAG_Double ); + AppendShort( a_Buffer, (short)itr->first.size() ); + if( itr->first.size() > 0 ) + { + a_Buffer.append( itr->first.c_str(), itr->first.size() ); + } + a_Buffer.push_back( itr->second ); + } + + for( FloatMap::iterator itr = m_Floats.begin(); itr != m_Floats.end(); itr++ ) + { + a_Buffer.push_back( TAG_Float ); + AppendShort( a_Buffer, (short)itr->first.size() ); + if( itr->first.size() > 0 ) + { + a_Buffer.append( itr->first.c_str(), itr->first.size() ); + } + a_Buffer.push_back( itr->second ); + } + + for( LongMap::iterator itr = m_Longs.begin(); itr != m_Longs.end(); itr++ ) + { + a_Buffer.push_back( TAG_Long ); + AppendShort( a_Buffer, (short)itr->first.size() ); + if( itr->first.size() > 0 ) + { + a_Buffer.append( itr->first.c_str(), itr->first.size() ); + } + a_Buffer.push_back( itr->second ); + } + + +} + +void cNBTCompound::PrintData( int a_Depth, std::string a_Name ) +{ + char* Prefix = new char[a_Depth*4+1]; + for(int i = 0; i < a_Depth*4; i++) + Prefix[i] = ' '; + Prefix[ a_Depth*4 ] = 0; + + if( a_Name.size() > 0 ) + printf("%sCOMPOUND (%s)\n", Prefix, a_Name.c_str() ); + else + printf("%sCOMPOUND (...)\n", Prefix ); + + delete Prefix; + a_Depth++; + Prefix = new char[a_Depth*4]; + for(int i = 0; i < a_Depth*4; i++) + Prefix[i] = ' '; + Prefix[ a_Depth*4-1 ] = 0; + + for( CompoundMap::iterator itr = m_Compounds.begin(); itr != m_Compounds.end(); itr++ ) + { + if( itr->second == 0 ) continue; + itr->second->PrintData( a_Depth, itr->first ); + } + + for( ListMap::iterator itr = m_Lists.begin(); itr != m_Lists.end(); itr++) + { + if( itr->second == 0 ) continue; + itr->second->PrintData( a_Depth, itr->first ); + } + + for( StringMap::iterator itr = m_Strings.begin(); itr != m_Strings.end(); itr++ ) + { + printf("%s STRING %s (%s)\n", Prefix, itr->first.c_str(), itr->second.c_str() ); + } + + for( IntegerMap::iterator itr = m_Integers.begin(); itr != m_Integers.end(); itr++ ) + { + printf("%s INTEGER %s (%i)\n", Prefix, itr->first.c_str(), itr->second ); + } + + for( ShortMap::iterator itr = m_Shorts.begin(); itr != m_Shorts.end(); itr++ ) + { + printf("%s SHORT %s (%i)\n", Prefix, itr->first.c_str(), itr->second ); + } + + for( FloatMap::iterator itr = m_Floats.begin(); itr != m_Floats.end(); itr++ ) + { + printf("%s FLOAT %s (%f)\n", Prefix, itr->first.c_str(), itr->second ); + } + + for( LongMap::iterator itr = m_Longs.begin(); itr != m_Longs.end(); itr++ ) + { + printf("%s LONG %s (%lli)\n", Prefix, itr->first.c_str(), itr->second ); + } + + for( DoubleMap::iterator itr = m_Doubles.begin(); itr != m_Doubles.end(); itr++ ) + { + printf("%s Double %s (%f)\n", Prefix, itr->first.c_str(), itr->second ); + } + + for( ByteMap::iterator itr = m_Bytes.begin(); itr != m_Bytes.end(); itr++ ) + { + printf("%s BYTE %s (%i)\n", Prefix, itr->first.c_str(), itr->second ); + } + + for( ByteArrayMap::iterator itr = m_ByteArrays.begin(); itr != m_ByteArrays.end(); itr++ ) + { + printf("%s BYTE ARRAY %s (length: %li)\n", Prefix, itr->first.c_str(), sizeof(itr->second) ); + } + + delete Prefix; +} + +void cNBTData::PrintData() +{ + printf("==== STRUCTURED NBT DATA ====\n"); + m_CurrentCompound->PrintData( 0, " " ); + printf("=============================\n"); +} + +void cNBTData::Serialize() +{ + std::string Buffer; + m_CurrentCompound->Serialize( Buffer ); + + if( m_Buffer ) + delete m_Buffer; + m_Buffer = new char[Buffer.size()]; + memcpy( m_Buffer, Buffer.c_str(), Buffer.size() ); + m_BufferSize = Buffer.size(); + + //printf("m_BufferSize1: %i\n", m_BufferSize);//re + + //for(unsigned int i = 0; i < m_BufferSize; i++)//re + //{//re + // printf("%02i %02x %3i %c\n", i, (unsigned char)m_Buffer[i], (unsigned char)m_Buffer[i], m_Buffer[i] );//re + //}//re +} + +void cNBTData::ParseData() +{ + if(!m_bDecompressed) + { + printf("WARNING: ParseData() called while data was not decompressed\n"); + return; + } + + m_Index = 0; + //printf("m_BufferSize2: %i\n", m_BufferSize);//re + //printf("cNBTData::ParseData()\n");//re + //for(unsigned int i = 0; i < m_BufferSize; i++)//re + //for(unsigned int i = 0; i < 70; i++)//re + //{//re + // printf("echo%02i %02x %3i %c\n", i, (unsigned char)m_Buffer[i], (unsigned char)m_Buffer[i], m_Buffer[i] );//re + //}//re + + while( m_Index < m_BufferSize ) + { + if (tm) { + printf("m_BufferSize3: %i\n", m_BufferSize); + printf("m_Index: %i\n", m_Index); + } + ParseTags(); + } +} + +void cNBTData::ParseTags() +{ + if( m_Index < m_BufferSize ) + { + //printf("ParseTags idx:%02i %02x %3i %c\n", m_Index, (unsigned char)m_Buffer[m_Index], (unsigned char)m_Buffer[m_Index], m_Buffer[m_Index] );//re + ENUM_TAG Tag = (ENUM_TAG)m_Buffer[m_Index]; + if( Tag > 0 && m_ParseFunctions[ Tag ] ) + { + //printf("m_BufferSize4: %i\n", m_BufferSize); + //printf("m_Index1: %i\n\n\n\n", m_Index); + + m_Index++; + if (tm) { + printf("Tag: %i\n", Tag); + } + (*this.*m_ParseFunctions[ Tag ])(true); + } + else if( Tag == TAG_End ) + { + if (tm) { + printf("Tag End\n"); + int n; + std::cin >> n; + } + m_Index++; + } + else + { + printf("UNKNOWN TAG %x\n", m_Buffer[m_Index] ); + for(unsigned int i = (m_Index-10 > 0)?m_Index-10:0 ; i < m_Index+10 && i < m_BufferSize; i++) + { + printf("%02i %02x %3i %c\n", i, (unsigned char)m_Buffer[i], (unsigned char)m_Buffer[i], m_Buffer[i] ); + } + m_Index = m_BufferSize; + return; + } + } +} + +void cNBTData::ParseCompound( bool a_bNamed ) +{ + std::string Name; + if( a_bNamed ) Name = ReadName(); + //printf("OPEN COMPOUND: %s\n", Name.c_str() );//re + + PutCompound( Name ); + OpenCompound( Name ); + while( m_Index < m_BufferSize && m_Buffer[ m_Index ] != TAG_End ) + { + ParseTags(); + } + CloseCompound(); + m_Index++; + //printf("CLOSE COMPOUND\n");//re +} + +void cNBTData::ParseList( bool a_bNamed ) +{ + std::string Name; + if( a_bNamed ) Name = ReadName(); + ENUM_TAG TagType = (ENUM_TAG)ReadByte(); + int Length = ReadInt(); + //printf("LIST: %s Type: %02x Length: %i\n", Name.c_str(), TagType, Length );//re + + //for(unsigned int i = (m_Index-10 > 0)?m_Index-10:0 ; i < m_Index+10 && i < m_BufferSize; i++)//re + //{//re + //printf("%02i %02x %3i %c\n", i, (unsigned char)m_Buffer[i], (unsigned char)m_Buffer[i], m_Buffer[i] );//re + //}//re + + if (tm) { + printf("List Name, tag, length: %s, %i, %i\n", Name.c_str(), (int)TagType, Length); + } + + PutList( Name, TagType ); + OpenList( Name ); + for(int i = 0; i < Length && m_Index < m_BufferSize; i++) + { + if( m_ParseFunctions[ TagType ] ) + { + (*this.*m_ParseFunctions[ TagType ] )(false); + } + } + if (tm) { + printf("List Done Name, tag, length: %s, %i, %i\n", Name.c_str(), (int)TagType, Length); + } + + CloseList(); + +} + +void cNBTData::ParseByte( bool a_bNamed ) +{ + std::string Name; + if( a_bNamed ) Name = ReadName(); + char Value = ReadByte(); + + PutByte( Name, Value ); + if (tm) { + printf("BYTE: %s %i\n", Name.c_str(), Value );//re + } +} + +void cNBTData::ParseShort( bool a_bNamed ) +{ + std::string Name; + if( a_bNamed ) Name = ReadName(); + short Value = ReadShort(); + + PutShort( Name, Value ); + if (tm) { + printf("SHORT: %s %i\n", Name.c_str(), Value );//re + } +} + +void cNBTData::ParseInt( bool a_bNamed ) +{ + std::string Name; + if( a_bNamed ) Name = ReadName(); + int Value = ReadInt(); + + PutInteger( Name, Value ); + if (tm) { + printf("INT: %s %i\n", Name.c_str(), Value );//re + } +} + +void cNBTData::ParseLong( bool a_bNamed ) +{ + if (tm) { + for(unsigned int i = (m_Index-10 > 0)?m_Index-10:0 ; i < m_Index+30 && i < m_BufferSize; i++) { + printf("%02i %02x %3i %c\n", i, (unsigned char)m_Buffer[i], (unsigned char)m_Buffer[i], m_Buffer[i] ); + } + } + std::string Name; + if( a_bNamed ) Name = ReadName(); + long long Value = ReadLong(); + + //PutInteger( Name, (int)Value ); + PutLong( Name, Value ); + if (tm) { + printf("LONG: %s %lli\n", Name.c_str(), Value );//re + } +} + +void cNBTData::ParseDouble( bool a_bNamed ) +{ + if (tm) { + for(unsigned int i = (m_Index-10 > 0)?m_Index-10:0 ; i < m_Index+30 && i < m_BufferSize; i++) { + printf("%02i %02x %3i %c\n", i, (unsigned char)m_Buffer[i], (unsigned char)m_Buffer[i], m_Buffer[i] ); + } + } + std::string Name; + if( a_bNamed ) Name = ReadName(); + double Value = ReadDouble(); + + //PutInteger( Name, (int)Value ); + PutDouble( Name, Value ); + if (tm) { + printf("Double: %s %f\n", Name.c_str(), Value );//re + } +} + +void cNBTData::ParseFloat( bool a_bNamed ) +{ + if (tm) { + for(unsigned int i = (m_Index-10 > 0)?m_Index-10:0 ; i < m_Index+30 && i < m_BufferSize; i++) { + printf("%02i %02x %3i %c\n", i, (unsigned char)m_Buffer[i], (unsigned char)m_Buffer[i], m_Buffer[i] ); + } + } + std::string Name; + if( a_bNamed ) Name = ReadName(); + float Value = ReadFloat(); + + //PutInteger( Name, (int)Value ); + PutFloat( Name, Value ); + if (tm) { + printf("Float: %s %f\n", Name.c_str(), Value );//re + } +} + +void cNBTData::ParseString( bool a_bNamed ) +{ + std::string Name; + if( a_bNamed ) Name = ReadName(); + std::string String = ReadName(); + + PutString( Name, String ); + if (tm) { + printf("STRING: %s (%s)\n", Name.c_str(), String.c_str() );//re + } +} + +void cNBTData::ParseByteArray( bool a_bNamed ) +{ + + std::string Name; + if( a_bNamed ) Name = ReadName(); + + int Length = ReadInt(); + std::string String; + + char* ByteArray = new char[ Length ]; + if( Length > 0 ) + { + memcpy( ByteArray, &m_Buffer[ m_Index ], Length ); + m_Index += Length; + } + + PutByteArray( Name, ByteArray ); + + if (tm) { + for(unsigned int i = (m_Index-10 > 0)?m_Index-10:0 ; i < m_Index+10 && i < m_BufferSize; i++) { + printf("%02i %02x %3i %c\n", i, (unsigned char)m_Buffer[i], (unsigned char)m_Buffer[i], m_Buffer[i] ); + } + } +} + +std::string cNBTData::ReadName() +{ + //printf("crui1 \n"); + short Length = ReadShort(); + + //printf("crui Length: %i\n", Length); + std::string Name; + if( Length > 0 ) + { + for(int i = 0; i < Length; i++, m_Index++) + { + Name.push_back( m_Buffer[m_Index] ); + } + } + return Name; +} + +char cNBTData::ReadByte() +{ + unsigned char Byte = m_Buffer[ m_Index ]; m_Index++; + return Byte; +} + +short cNBTData::ReadShort() +{ + short Length = 0; + Length |= m_Buffer[ m_Index ] << 8; m_Index++; + Length |= m_Buffer[ m_Index ]; m_Index++; + return Length; +} + +int cNBTData::ReadInt() +{ + int Value = 0; + memcpy( &Value, m_Buffer+m_Index, sizeof(int) ); + m_Index+=sizeof(int); + + return ntohl( Value ); +} + +long long cNBTData::ReadLong() +{ + if (tm) { + printf( "here1 : %i, m_Index: %i\n", (int)sizeof(long long), (int)m_Index ); + } + long long Value = 0; + memcpy( &Value, m_Buffer+m_Index, sizeof(long long) ); + m_Index+=sizeof(long long); + if (tm) { + printf( "here2 : %i, m_Index: %i\n", (int)sizeof(long long), (int)m_Index ); + } + return Value; +} + +double cNBTData::ReadDouble() +{ + double Value = 0; + memcpy( &Value, m_Buffer+m_Index, sizeof(double) ); + m_Index+=sizeof(double); + + return Value; +} + +float cNBTData::ReadFloat() +{ + float Value = 0; + memcpy( &Value, m_Buffer+m_Index, sizeof(float) ); + m_Index+=sizeof(float); + + return Value; +} + +void cNBTCompound::PutList( std::string Name, ENUM_TAG Type ) +{ + m_Lists[Name] = new cNBTList( m_CurrentList, Type ); +} + +void cNBTCompound::PutCompound( std::string Name ) +{ + if( m_CurrentList ) + { + m_CurrentList->AddToList( new cNBTCompound( this ) ); + } + else + { + m_Compounds[Name] = new cNBTCompound( this ); + } +} + +void cNBTCompound::PutFloat( std::string Name, float Value ) +{ + if( m_CurrentList ) + m_CurrentList->AddToList( (void*)((unsigned int*)&Value) ); + else + m_Floats[Name] = Value; +} + +cNBTCompound* cNBTCompound::GetCompound( std::string Name ) +{ + if( m_CurrentList ) + { + if( m_CurrentList->GetType() != TAG_Compound ) + return 0; + + return (cNBTCompound*)m_CurrentList->GetLastElement(); + } + return m_Compounds[Name]; +} + +void cNBTList::PrintData(int a_Depth, std::string a_Name) +{ + char* Prefix = new char[a_Depth*4]; + for(int i = 0; i < a_Depth*4; i++) + Prefix[i] = ' '; + Prefix[ a_Depth*4-1 ] = 0; + + if( a_Name.size() > 0 ) + printf("%s LIST (%s)\n", Prefix, a_Name.c_str() ); + else + printf("%s LIST\n", Prefix ); + + delete [] Prefix; + + for( VoidList::iterator itr = m_List.begin(); itr != m_List.end(); itr++) + { + switch( m_Type ) + { + case cNBTCompound::TAG_Compound: + { + ((cNBTCompound*)*itr)->PrintData(a_Depth+1, "..."); + } + break; + default: + break; + } + } +} + +void cNBTList::Serialize(std::string & a_Buffer) +{ + for( VoidList::iterator itr = m_List.begin(); itr != m_List.end(); itr++ ) + { + switch( m_Type ) + { + case cNBTCompound::TAG_Compound: + { + ((cNBTCompound*)(*itr))->Serialize( a_Buffer ); + a_Buffer.push_back( cNBTCompound::TAG_End ); + } + break; + default: + break; + } + } +} + +void cNBTData::Clear() +{ + while( m_CurrentCompound != this ) CloseCompound(); + m_CurrentCompound->Clear(); + + if( m_Buffer ) + { + delete m_Buffer; + m_Buffer = 0; + } + m_BufferSize = 0; +} + +void cNBTCompound::Clear() +{ + for( CompoundMap::iterator itr = m_Compounds.begin(); itr != m_Compounds.end(); itr++ ) + { + if( itr->second == 0 ) continue; + itr->second->Clear(); + delete itr->second; + itr->second = 0; + } + m_Compounds.clear(); + + for( ListMap::iterator itr = m_Lists.begin(); itr != m_Lists.end(); itr++ ) + { + if( itr->second == 0 ) continue; + itr->second->Clear(); + delete itr->second; + itr->second = 0; + } + m_Lists.clear(); + m_Bytes.clear(); + m_Shorts.clear(); + m_Integers.clear(); + m_Strings.clear(); +} + +void cNBTList::Clear() +{ + for( VoidList::iterator itr = m_List.begin(); itr != m_List.end(); itr++) + { + switch( m_Type ) + { + case cNBTCompound::TAG_Compound: + { + cNBTCompound* Compound = (cNBTCompound*)(*itr); + Compound->Clear(); + delete Compound; + *itr = 0; + } + break; + case cNBTCompound::TAG_List: + { + cNBTList* List = (cNBTList*)(*itr); + List->Clear(); + delete List; + *itr = 0; + } + break; + default: + break; + } + } + m_List.clear(); +} |