summaryrefslogblamecommitdiffstats
path: root/World.cpp
blob: dfd3b6046b4717fdf664c887ad9645a3e96b6380 (plain) (tree)

























































































































































































































                                                                                                                  
#include <iostream>
#include <bitset>
#include "World.hpp"


Block &World::GetBlock(PositionI pos) {
    //unsigned long long pos = (unsigned long long) x << 32;
    //pos |= y;
    return m_blocks[pos];
}

void World::SetBlock(PositionI pos, Block block) {
    //unsigned long long pos = (unsigned long long) x << 32;
    //pos |= y;
    m_blocks[pos] = block;
}

void World::ParseChunkData(Packet packet) {
    int chunkX = packet.GetField(0).GetInt();
    int chunkZ = packet.GetField(1).GetInt();
    bool isGroundContinuous = packet.GetField(2).GetBool();
    std::bitset<16> bitmask(packet.GetField(3).GetVarInt());
    int entities = packet.GetField(5).GetVarInt();

    size_t dataLen = packet.GetField(5).GetLength();
    byte *content = new byte[dataLen];
    packet.GetField(5).CopyToBuff(content);

    std::cout << "Chunk " << chunkX << "x" << chunkZ << std::endl;
    std::cout << "\tGround continuous: " << (isGroundContinuous ? "true" : "false") << std::endl;
    std::cout << "\tPrimary bitmask: " << bitmask << std::endl;
    std::cout << "\tDataLen: " << dataLen << std::endl;
    std::cout << "\tEntities: " << entities << std::endl;

    if (isGroundContinuous)
        dataLen -= 256;

    byte *biomes = content + packet.GetField(5).GetLength() - 256;
    for (int i = 0; i < 1; i++) {
        if (bitmask[i]) {
            size_t len = ParseSectionData(chunkX, chunkZ, isGroundContinuous, i, content);
            //content += len;
            //std::cout << "\t Size of section is " << len << std::endl;
        }
    }
    std::cout << std::dec << std::endl;
    fflush(stdout);
}

size_t World::ParseSectionData(int chunkX, int chunkZ, bool isGroundContinous, int section, byte *data) {
    Field fBitsPerBlock = FieldParser::Parse(UnsignedByte, data);
    byte bitsPerBlock = fBitsPerBlock.GetUByte();
    data += fBitsPerBlock.GetLength();

    bool usePalette = bitsPerBlock <= 8;
    Field fPaletteLength = FieldParser::Parse(VarInt, data);
    int paletteLength = fPaletteLength.GetVarInt();
    data += fPaletteLength.GetLength();

    std::cout << "Section: " << chunkX << "x" << chunkZ << "x" << section << std::endl;
    std::cout << "\tBits per block: " << (int) bitsPerBlock << std::endl;
    std::cout << "\tPalette length: " << paletteLength << std::endl;
    std::vector<int> palette;
    std::map<unsigned char, unsigned short> pal;
    if (paletteLength > 0) {
        for (unsigned char i = 0; i < paletteLength; i++) {
            endswap(&i);
            Field f = FieldParser::Parse(VarInt, data);
            data += f.GetLength();
            palette.push_back(f.GetVarInt());
            std::cout << "\t\tPalette[" << std::bitset<8>(i) << "]: " << std::bitset<13>(palette[i]) << std::endl;
            pal[i] = f.GetVarInt();
            endswap(&i);
        }
    }

    Field fDataLength = FieldParser::Parse(VarInt, data);
    data += fDataLength.GetLength();
    int dataLength = fDataLength.GetVarInt();
    size_t dataSize = dataLength * 8;
    std::cout << "\tData length: " << dataLength << " (" << dataSize << ")" << std::endl;

    std::vector<unsigned short> blocks = ParseBlocks(data, dataLength, palette, bitsPerBlock);
    std::cout << "\tChunk content: ";
    int i = 0;
    for (int y = 0; y < SECTION_LENGTH; y++) {
        for (int z = 0; z < SECTION_HEIGHT; z++) {
            for (int x = 0; x < SECTION_WIDTH; x++) {
                int X = chunkX * SECTION_WIDTH + x;
                int Y = section * SECTION_HEIGHT + y;
                int Z = chunkZ * SECTION_LENGTH + z;
                //std::cerr<<"Block at "<<X<<" "<<Y<<" "<<Z<<std::endl;
                Block block(usePalette ? pal[blocks[i]] : blocks[i],15);
                SetBlock(PositionI(X, Z, Y), block);
                std::cout << (PositionI(X, Z, Y).GetY()) << ": "
                          << block.GetId() << "\t";
                //<< (usePalette ? pal[blocks[i]] : blocks[i]) << "\t";
                //<< std::bitset<13>(usePalette ? pal[blocks[i]] : blocks[i]) << "\t";
                i++;
            }
        }
    }
    std::cout << std::endl;
    /*for (auto it:blocks) {
        //auto m = std::bitset<4>(it).to_string();
        //std::cout<<m<<" ";
        std::cout<<std::bitset<13>(pal[it])<<" ";
        //std::cout << (m=="1000" || m =="0100" || m=="0010"?"":m+" ");
    }*/
    return (dataSize + (m_dimension == 0 ? dataSize : 0) / 2 + dataSize / 2);
}

std::vector<unsigned short>
World::ParseBlocks(byte *bytes, int dataLength, std::vector<int> palette, byte bitsPerBlock) {
    std::vector<unsigned short> blocks;
    for (int i = 0; i < blocks.size(); i++) {
        blocks[i] = 0;
    }
    byte *data = new byte[dataLength * 8];
    size_t arrLength = dataLength * 8;
    byte *ptr = data;
    for (int i = 0; i < dataLength; i++) {
        Field fData = FieldParser::Parse(Long, bytes);
        bytes += fData.GetLength();
        *reinterpret_cast<long long *>(ptr) = fData.GetLong();
        ptr += 8;
    }
    int bitPos = 0;
    unsigned short t = 0;
    for (int i = 0; i < arrLength; i++) {
        //endswap(&data[i]);
        //std::bitset<8> bitset1 = std::bitset<8>(data[i]);
        //std::cout << bitset1 << ": ";
        for (int j = 0; j < 8; j++) {
            //std::bitset<8> bitset2 = std::bitset<8>(t);
            /*std::cout << bitset2 << "_";
            std::cout << bitset1 << "\t";
            fflush(stdout);*/

            t |= (data[i] & 0x01) ? 0x80 : 0x00;
            t >>= 1;
            data[i] >>= 1;
            bitPos++;
            if (bitPos >= bitsPerBlock) {
                bitPos = 0;
                //endswap(&t);
                t >>= bitsPerBlock - 1;
                blocks.push_back(t);
                //std::cout << bitset2 << "\t";
                t = 0;
            }
            /*bitset1 = std::bitset<8>(data[i]);
            bitset2 = std::bitset<8>(t);*/
        }
    }
    //std::cout << std::endl;
    /*int bitPos = 0, bytePos = 0, pushedBlocks = 0, bits = 0;
    unsigned short t = 0;
    while (bytePos < arrLength) {
        //std::cout << std::bitset<8>(data[bytePos]) << " ";
        //int bit = data[bytePos] & 1;
        t|=(data[bytePos] & 1)<<bitPos;
        data[bytePos] = data[bytePos]>>1;


        //t = t | ((data[bytePos]<<bitPos) & 1);
        std::cout<<std::bitset<8>(t)<<"\t";
        if (bitPos >= 7) {
            bitPos = 0;
            bytePos++;
            blocks[pushedBlocks] = t;
            std::cout<<std::bitset<13>(t)<<"\t";
            t = 0;
        } else {
            bitPos++;
        }

        bits++;
        if (bits>=bitsPerBlock){
            bits=0;
            bitPos=0;
            bytePos++;
            blocks[pushedBlocks] = t;
            std::cout<<std::bitset<13>(t)<<"+\t";
            t = 0;
        } else {
            t <<= 1;
        }
        fflush(stdout);
    }*/
    //
    /*int shift = 0;
    int bx = 0;
    for (int bytmass = 0; bytmass < arrLength; bytmass++) {
        unsigned char bitinbyte = 7;
        int block = 0;
        for (int posbit = 7; posbit > 0; posbit--) {
            int b = (data[bytmass] >> posbit);
            blocks[block + shift] = blocks[block + shift] | (b << bx);
            bx++;
            if (bx > bitsPerBlock) {
                bx = 0;
                if (shift == 0) shift = 1;
                if (shift == 1) {
                    shift = 0;
                    block++;
                    if ((block * 2) > blocks.size()) {
                        std::cout<<block*2<<">"<<blocks.size()<<std::endl;
                        throw 124;
                    }
                }
            }
        }
    }*/
    //
    delete[] data;
    return blocks;
}