#include "common/BlockStorage.h" static constexpr Block::Id EMPTY_BLOCK = 65535; BlockStorage::Map::Map(int length, Block::Id id) : blocks(length, 1) { blocks.fill(0); map.reserve(2); map.add(id); map.add(EMPTY_BLOCK); } Block::Id BlockStorage::Map::get(int index) const { return map[blocks.get(index)]; } void BlockStorage::Map::set(int index, Block::Id id) { for(int i = 0; i < map.getLength(); i++) { if(map[i] == id) { blocks.set(index, i); return; } else if(map[i] == EMPTY_BLOCK) { map[i] = id; blocks.set(index, i); return; } } blocks.resize(blocks.getBits() + 1); int mapId = map.getLength(); map.resize(mapId * 2, EMPTY_BLOCK); map[mapId] = id; blocks.set(index, mapId); } BlockStorage::BlockStorage(int sizeBits, int heightBits) : size(1 << sizeBits), height(1 << heightBits), sizeMask(size - 1) { maps.resize((size * size * height) / SEGMENT); } Block::Id BlockStorage::get(int x, int y, int z) const { if(y < 0 || y >= height) { return y < 0; } x &= (size - 1); z &= (size - 1); int index = y * size * size + x * size + z; int segmentIndex = index >> SEGMENT_BITS; if(maps[segmentIndex] == nullptr) { return 0; } return maps[segmentIndex]->get(index & SEGMENT_MASK); } void BlockStorage::set(int x, int y, int z, Block::Id id) { if(y < 0 || y >= height) { return; } x &= (size - 1); z &= (size - 1); int index = y * size * size + x * size + z; int segmentIndex = index >> SEGMENT_BITS; if(maps[segmentIndex] == nullptr) { if(id == 0) { return; } maps[segmentIndex] = new Map(SEGMENT, 0); } maps[segmentIndex]->set(index & SEGMENT_MASK, id); } int BlockStorage::getSize() const { return size; } int BlockStorage::getHeight() const { return height; }