Chunk* WorldRegion::loadChunk(ChunkPillar& parent, wCoord x, wCoord y, wCoord z) { size_t index = getChunkIndex(x, y, z); uint32_t offset = mChunkOffsets[index]; if (offset != 0) { try { // Chunk is saved, load it uint32_t sector = getSectorFromOffset(offset); uint8_t sectorSize = getSectorSizeFromOffset(offset); bio::gzip_decompressor gzDecomp; bio::filtering_istream gzIn; gzIn.push(gzDecomp); mChunkFile.seekg(sector * ChunkFileSectorSize); gzIn.push(mChunkFile); return parent.createChunkFromStream(y, gzIn); } catch (bio::gzip_error& e) { // Something was wrong with this chunk, ignore it std::cout << "WorldRegion::loadChunk: gzip exception: " << e.what() << std::endl; return 0; } } // Chunk not yet generated return 0; }
/** * This method tries to load a chunk from the region data and returns a status. */ int RegionFile::loadChunk(const ChunkPos& pos, Chunk& chunk) { int index = getChunkIndex(pos); // check if the chunk exists if (chunk_data[index].size() == 0) return CHUNK_DOES_NOT_EXIST; // get compression type and size of the data uint8_t compression = chunk_data_compression[index]; nbt::Compression comp = nbt::Compression::NO_COMPRESSION; if (compression == 1) comp = nbt::Compression::GZIP; else if (compression == 2) comp = nbt::Compression::ZLIB; int size = chunk_data[index].size(); // set the chunk rotation chunk.setRotation(rotation); chunk.setWorldCrop(world_crop); // try to load the chunk try { if (!chunk.readNBT(reinterpret_cast<char*>(&chunk_data[index][0]), size, comp)) return CHUNK_DATA_INVALID; } catch (const nbt::NBTError& err) { std::cout << "Error: Unable to read chunk at " << pos << " : " << err.what() << std::endl; return CHUNK_NBT_ERROR; } return CHUNK_OK; }
void Chunks::setDataChanged(qint64 pos, bool dataChanged) { if ((pos < 0) || (pos >= _size)) return; int chunkIdx = getChunkIndex(pos); qint64 posInBa = pos - _chunks[chunkIdx].absPos; _chunks[chunkIdx].dataChanged[(int)posInBa] = char(dataChanged); }
bool Chunks::insert(qint64 pos, char b) { if ((pos < 0) || (pos > _size)) return false; int chunkIdx; if (pos == _size) chunkIdx = getChunkIndex(pos-1); else chunkIdx = getChunkIndex(pos); qint64 posInBa = pos - _chunks[chunkIdx].absPos; _chunks[chunkIdx].data.insert(posInBa, b); _chunks[chunkIdx].dataChanged.insert(posInBa, char(1)); for (int idx=chunkIdx+1; idx < _chunks.size(); idx++) _chunks[idx].absPos += 1; _size += 1; _pos = pos; return true; }
bool Chunks::overwrite(qint64 pos, char b) { if ((pos < 0) || (pos >= _size)) return false; int chunkIdx = getChunkIndex(pos); qint64 posInBa = pos - _chunks[chunkIdx].absPos; _chunks[chunkIdx].data[(int)posInBa] = b; _chunks[chunkIdx].dataChanged[(int)posInBa] = char(1); _pos = pos; return true; }
bool Chunks::removeAt(qint64 pos) { if ((pos < 0) || (pos >= _size)) return false; int chunkIdx = getChunkIndex(pos); qint64 posInBa = pos - _chunks[chunkIdx].absPos; _chunks[chunkIdx].data.remove(posInBa, 1); _chunks[chunkIdx].dataChanged.remove(posInBa, 1); for (int idx=chunkIdx+1; idx < _chunks.size(); idx++) _chunks[idx].absPos -= 1; _size -= 1; _pos = pos; return true; }
void RegionFile::setChunkData(const ChunkPos& chunk, const std::vector<uint8_t>& data, uint8_t compression) { int index = getChunkIndex(chunk); chunk_data[index] = data; chunk_data_compression[index] = compression; if (data.size() == 0) { chunk_exists[index] = false; containing_chunks.erase(chunk); } else { chunk_exists[index] = true; containing_chunks.insert(chunk); } }
void MemBufferEntry::initializeData(MemOpsType::iterator mit) { mit--; // skip itself MemBufferEntry *prevEntry = *mit; if (prevEntry->getChunkIndex() == getChunkIndex()) { // Copy from previous version I(prevEntry!=this); I(*(prevEntry->getVersionRef()) < *ver); initializeData(prevEntry); }else{ // Copy from memory chunkCopy(getAddr(), getRealAddr(), chunkDataMask); } }
Chunk* ChunkPillar::getChunkLocal(wCoord y) { size_t index = getChunkIndex(y); Chunk* curChunk = mChunks[index]; if (curChunk == 0) { wCoord yAbs = (y > ChunksAboveZero ? y - ChunksPerPillar : y); curChunk = mWRegion.loadChunk(*this, mX, yAbs, mZ); if (curChunk == 0) { if (maxY > yAbs * ChunkSizeY) { // Chunk has blocks curChunk = createChunk(yAbs); mWRegion.getTerraGen().fillChunk(*this, *static_cast<ChunkBase*>(curChunk)); } else { // Chunk is empty curChunk = createChunkEmpty(yAbs); } } mChunks[index] = curChunk; } return curChunk; };
uint32_t WorldRegion::findFreeChunkSectorOffset(Chunk* chunk, uint32_t neededSize) { size_t index = getChunkIndex(chunk->mX, chunk->mY, chunk->mZ); uint8_t neededSectors = (neededSize / ChunkFileSectorSize) + 1; uint32_t offset = mChunkOffsets[index]; if (getSectorSizeFromOffset(offset) < neededSectors) { // Need more space, search a bigger place // At first, mark old sectors as free for (uint32_t i = getSectorFromOffset(offset); i < getSectorSizeFromOffset(offset); ++i) { mFreeChunkSectors[i] = true; } // Set result to not found offset = 0; // Now search for a big enough space auto startIt = mFreeChunkSectors.begin(); auto endIt = mFreeChunkSectors.end(); while (startIt != endIt) { // Find first free auto posIt = std::find(startIt, endIt, true); // Save first free for index calculation startIt = posIt; // Test if enough space is free uint8_t free; for (free = 1; free < neededSectors; ++free) { ++posIt; if (*posIt == false || posIt == endIt) { break; } } if (free == neededSectors) { // Found big enough place uint32_t sector = std::distance(mFreeChunkSectors.begin(), startIt); offset = makeOffset(sector, neededSectors); if (sector + neededSectors > mFreeChunkSectors.size()) { mFreeChunkSectors.resize(mFreeChunkSectors.size() * 2, true); } // Mark found sectors as used mChunkOffsets[index] = offset; for (uint32_t i = sector; i < sector + neededSectors; ++i) { mFreeChunkSectors[i] = false; } break; } else { // not big enough, start over startIt = posIt; } } } else { // Old space is big enough, reuse it } return offset; }
uint8_t RegionFile::getChunkDataCompression(const ChunkPos& chunk) const { return chunk_data_compression[getChunkIndex(chunk)]; }
const std::vector<uint8_t>& RegionFile::getChunkData(const ChunkPos& chunk) const { return chunk_data[getChunkIndex(chunk)]; }
void RegionFile::setChunkTimestamp(const ChunkPos& chunk, uint32_t timestamp) { chunk_timestamps[getChunkIndex(chunk)] = timestamp; }
int RegionFile::getChunkTimestamp(const ChunkPos& chunk) const { return chunk_timestamps[getChunkIndex(chunk)]; }
bool RegionFile::hasChunk(const ChunkPos& chunk) const { return chunk_exists[getChunkIndex(chunk)]; }
/** * This is a helper method that goes from chunk to file position. * * @param chunk The chunk to locate in the file. * @returns The position to start reading or writing at */ BigInt CubeTileHandler::getTileStartByte(const RawCubeChunk &chunk) const { return getDataStartByte() + getChunkIndex(chunk) * getBytesPerChunk(); }