#include "Section.hpp" #include #include void Section::CalculateHash() const { if (block.empty()) { hash = 0; return; } size_t offset = 0; std::vector rawData; rawData.resize(block.size() * sizeof(long long) + light.size() + sky.size()); std::memcpy(rawData.data() + offset, block.data(), block.size() * sizeof(BlockId)); offset += block.size() * sizeof(BlockId); std::memcpy(rawData.data() + offset, light.data(), light.size() * sizeof(unsigned char)); offset += light.size() * sizeof(unsigned char); if (!sky.empty()) std::memcpy(rawData.data() + offset, sky.data(), sky.size() * sizeof(unsigned char)); for (auto& it : overrideList) { rawData.push_back(*reinterpret_cast (&it.second) & 0xF); rawData.push_back(*reinterpret_cast (&it.second) >> 0xF); } const unsigned char *from = reinterpret_cast(rawData.data()); size_t length = rawData.size(); std::string str(from, from + length); hash = std::hash{}(str); } Section::Section(Vector pos, unsigned char bitsPerBlock, std::vector palette, std::vector blockData, std::vector lightData, std::vector skyData) { if (bitsPerBlock < 4) bitsPerBlock = 4; if (bitsPerBlock > 8) bitsPerBlock = 13; this->bitsPerBlock = bitsPerBlock; this->worldPosition = pos; this->block = std::move(blockData); this->palette = std::move(palette); this->light = std::move(lightData); this->sky = std::move(skyData); hash = -1; } BlockId Section::GetBlockId(Vector pos) const { if (block.empty()) return BlockId{ 0,0 }; if (!overrideList.empty()) { auto iter = overrideList.find(pos); if (iter != overrideList.end()) return iter->second; } int value; unsigned char individualValueMask = ((1 << bitsPerBlock) - 1); int blockNumber = (((pos.y * 16) + pos.z) * 16) + pos.x; int startLong = (blockNumber * bitsPerBlock) / 64; int startOffset = (blockNumber * bitsPerBlock) % 64; int endLong = ((blockNumber + 1) * bitsPerBlock - 1) / 64; unsigned char t; if (startLong == endLong) { t = (block[startLong] >> startOffset); } else { int endOffset = 64 - startOffset; t = (block[startLong] >> startOffset |block[endLong] << endOffset); } t &= individualValueMask; if (t >= palette.size()) { //LOG(ERROR) << "Out of palette: " << t; value = 0; } else value = palette[t]; BlockId blockId; blockId.id = value >> 4; blockId.state = value & 0xF; return blockId; } unsigned char Section::GetBlockLight(Vector pos) const { if (light.empty()) return 0; int blockNumber = pos.y * 256 + pos.z * 16 + pos.x; unsigned char lightValue = this->light[blockNumber / 2]; return (blockNumber % 2 == 0) ? (lightValue & 0xF) : (lightValue >> 4); } unsigned char Section::GetBlockSkyLight(Vector pos) const { if (sky.empty()) return 0; int blockNumber = pos.y * 256 + pos.z * 16 + pos.x; unsigned char skyValue = this->sky[blockNumber / 2]; return (blockNumber % 2 == 0) ? (skyValue & 0xF) : (skyValue >> 4); } void Section::SetBlockId(Vector pos, BlockId value) { overrideList[pos] = value; hash = -1; } Vector Section::GetPosition() const { return worldPosition; } size_t Section::GetHash() const { if (hash == -1) CalculateHash(); return hash; }