summaryrefslogtreecommitdiffstats
path: root/src/world/Section.cpp
blob: ac34fbab8c4ffd9d1efc869cb6cb3548577ceafd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "Section.hpp"

Section::Section(byte *dataBlocks, size_t dataBlocksLength, byte *dataLight, byte *dataSky, byte bitsPerBlock,
                 std::vector<unsigned short> palette) {
    m_dataBlocksLen = dataBlocksLength;
    m_dataBlocks = new byte[m_dataBlocksLen];
    std::copy(dataBlocks, dataBlocks + m_dataBlocksLen, m_dataBlocks);

    m_dataLight = new byte[2048];
    std::copy(dataLight, dataLight + 2048, m_dataLight);

    if (dataSky) {
        m_dataSkyLight = new byte[2048];
        std::copy(dataSky, dataSky + 2048, m_dataSkyLight);
    }

    m_palette = palette;
    m_bitsPerBlock = bitsPerBlock;
}

Section::~Section() {
    delete[] m_dataBlocks;
    m_dataBlocksLen = 0;
    m_dataBlocks = nullptr;
    delete[] m_dataLight;
    m_dataLight = nullptr;
    delete[] m_dataSkyLight;
    m_dataSkyLight = nullptr;
}

Block &Section::GetBlock(Vector pos) {
    if (m_dataBlocks != nullptr) {
        std::mutex parseMutex;
        std::unique_lock<std::mutex> parseLocker(parseMutex);
        parseWaiter.wait(parseLocker);
        while (m_dataBlocks != nullptr) {
            parseWaiter.wait(parseLocker);
        }
    }
    return m_blocks[pos.GetY() * 256 + pos.GetZ() * 16 + pos.GetX()];
}

void Section::Parse() {
    if (m_dataBlocks == nullptr)
        return;

    long long *longArray = reinterpret_cast<long long *>(m_dataBlocks);
    for (int i = 0; i < m_dataBlocksLen / 8; i++)
        endswap(&longArray[i]);
    std::vector<unsigned short> blocks;
    blocks.reserve(4096);
    int bitPos = 0;
    unsigned short t = 0;
    for (int i = 0; i < m_dataBlocksLen; i++) {
        for (int j = 0; j < 8; j++) {
            t |= (m_dataBlocks[i] & 0x01) ? 0x80 : 0x00;
            t >>= 1;
            m_dataBlocks[i] >>= 1;
            bitPos++;
            if (bitPos >= m_bitsPerBlock) {
                bitPos = 0;
                t >>= m_bitsPerBlock - 1;
                blocks.push_back(t);
                t = 0;
            }
        }
    }

    std::vector<byte> light;
    light.reserve(4096);
    for (int i = 0; i < 2048; i++) {
        byte t = m_dataLight[i];
        byte first = t & 0b11110000;
        byte second = t >> 4;
        light.push_back(first);
        light.push_back(second);
    }
    for (int i = 0; i < 4096; i++) {
        unsigned short blockId = m_palette.size() > 0 ? m_palette[blocks[i]] : blocks[i];
        Block block(blockId, light[i]);
        m_blocks.push_back(block);
    }
    if ((light.size() + blocks.size()) / 2 != 4096) {
        throw 118;
    }
    delete[] m_dataBlocks;
    m_dataBlocksLen = 0;
    m_dataBlocks = nullptr;
    delete[] m_dataLight;
    m_dataLight = nullptr;
    delete[] m_dataSkyLight;
    m_dataSkyLight = nullptr;
    parseWaiter.notify_all();
}

Section &Section::operator=(Section other) {
    other.swap(*this);
    return *this;
}

void Section::swap(Section &other) {
    std::swap(other.m_dataBlocksLen, m_dataBlocksLen);
    std::swap(other.m_dataBlocks, m_dataBlocks);
    std::swap(other.m_dataLight, m_dataLight);
    std::swap(other.m_dataSkyLight, m_dataSkyLight);
    std::swap(other.m_blocks, m_blocks);
    std::swap(other.m_palette, m_palette);
    std::swap(other.m_bitsPerBlock, m_bitsPerBlock);
}

Section::Section(const Section &other) {
    m_dataBlocksLen = other.m_dataBlocksLen;
    m_dataBlocks = new byte[m_dataBlocksLen];
    std::copy(other.m_dataBlocks, other.m_dataBlocks + m_dataBlocksLen, m_dataBlocks);

    m_dataLight = new byte[2048];
    std::copy(other.m_dataLight, other.m_dataLight + 2048, m_dataLight);

    if (other.m_dataSkyLight) {
        m_dataSkyLight = new byte[2048];
        std::copy(other.m_dataSkyLight, other.m_dataSkyLight + 2048, m_dataSkyLight);
    }

    m_palette = other.m_palette;
    m_bitsPerBlock = other.m_bitsPerBlock;
}