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
|
#include <bitset>
#include <easylogging++.h>
#include "World.hpp"
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];
byte *contentOrigPtr = content;
packet.GetField(5).CopyToBuff(content);
if (isGroundContinuous)
dataLen -= 256;
byte *biomes = content + packet.GetField(5).GetLength() - 256;
for (int i = 0; i < 16; i++) {
if (bitmask[i]) {
size_t len = 0;
Vector chunkPosition = Vector(chunkX, i, chunkZ);
if (!m_sections.insert(std::make_pair(chunkPosition, ParseSection(content, len))).second)
LOG(ERROR) << "Chunk not created: " << chunkPosition;
auto sectionIter = m_sections.find(chunkPosition);
if (sectionIter == m_sections.end())
LOG(ERROR)<< "Created chunk not found: " << chunkPosition;
else
sectionIter->second.Parse();
content += len;
}
}
delete[] contentOrigPtr;
}
Section World::ParseSection(byte *data, size_t &dataLen) {
dataLen = 0;
Field fBitsPerBlock = FieldParser::Parse(UnsignedByte, data);
byte bitsPerBlock = fBitsPerBlock.GetUByte();
data += fBitsPerBlock.GetLength();
dataLen += fBitsPerBlock.GetLength();
Field fPaletteLength = FieldParser::Parse(VarInt, data);
int paletteLength = fPaletteLength.GetVarInt();
data += fPaletteLength.GetLength();
dataLen += fPaletteLength.GetLength();
std::vector<unsigned short> palette;
if (paletteLength > 0) {
for (unsigned char i = 0; i < paletteLength; i++) {
endswap(&i);
Field f = FieldParser::Parse(VarInt, data);
data += f.GetLength();
dataLen += f.GetLength();
palette.push_back(f.GetVarInt());
endswap(&i);
}
}
Field fDataLength = FieldParser::Parse(VarInt, data);
data += fDataLength.GetLength();
dataLen += fDataLength.GetLength();
int dataLength = fDataLength.GetVarInt();
size_t dataSize = dataLength * 8;
dataLen += dataSize;
byte *dataBlocks = data;
data += 2048;
dataLen += 2048;
byte *dataLight = data;
byte *dataSky = nullptr;
if (m_dimension == 0) {
data += 2048;
dataLen += 2048;
dataSky = data;
}
return Section(dataBlocks, dataSize, dataLight, dataSky, bitsPerBlock, palette);
}
World::~World() {
isContinue = false;
m_parseSectionWaiter.notify_all();
m_sectionParseThread.join();
}
void World::SectionParsingThread() {
while (isContinue) {
std::unique_lock<std::mutex> sectionParseLocker(m_parseSectionMutex);
m_parseSectionWaiter.wait(sectionParseLocker);
while (m_sectionToParse.size() == 0 && isContinue) {
m_parseSectionWaiter.wait(sectionParseLocker);
}
while (m_sectionToParse.size() > 0) {
auto it = m_sectionToParse.front();
m_sectionToParse.pop();
it->second.Parse();
}
}
}
World::World() {
m_sectionParseThread = std::thread(&World::SectionParsingThread, this);
}
|