World: Chunk: add support for unordered sections

MC1.18 doesn't always store sections sorted by their Y value, possibly
related to "optimize world".
This commit is contained in:
Matthias Schiffer 2021-12-12 12:18:18 +01:00
parent a2fe33ef1f
commit fac2e4c8da
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C

View file

@ -52,17 +52,35 @@ Chunk::Chunk(const ChunkData *data) {
auto dataVersionTag = data->getRoot()->get<NBT::IntTag>("DataVersion"); auto dataVersionTag = data->getRoot()->get<NBT::IntTag>("DataVersion");
uint32_t dataVersion = dataVersionTag ? dataVersionTag->getValue() : 0; uint32_t dataVersion = dataVersionTag ? dataVersionTag->getValue() : 0;
std::vector<std::unique_ptr<Section>> tmpSections;
section_idx_t minY = std::numeric_limits<section_idx_t>::max();
section_idx_t maxY = std::numeric_limits<section_idx_t>::min();
for (auto &sTag : *sectionsTag) { for (auto &sTag : *sectionsTag) {
auto s = std::dynamic_pointer_cast<const NBT::CompoundTag>(sTag); auto s = std::dynamic_pointer_cast<const NBT::CompoundTag>(sTag);
std::unique_ptr<Section> section = Section::makeSection(s, dataVersion); std::unique_ptr<Section> section = Section::makeSection(s, dataVersion);
section_idx_t Y = section->getY(); section_idx_t Y = section->getY();
if (sections.empty()) if (Y < minY)
sectionOffset = Y; minY = Y;
if (Y > maxY)
maxY = Y;
tmpSections.push_back(std::move(section));
}
if (tmpSections.empty())
return;
assertValue(minY <= maxY);
sectionOffset = minY;
sections.resize(maxY - minY + 1);
for (auto &section : tmpSections) {
section_idx_t Y = section->getY();
Y -= sectionOffset; Y -= sectionOffset;
assertValue(Y >= 0 && size_t(Y) >= sections.size()); assertValue(Y >= 0 && size_t(Y) < sections.size());
sections.resize(Y); assertValue(!sections[Y]);
sections.push_back(std::move(section)); sections[Y] = std::move(section);
} }
} }