예제 #1
0
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;
}
예제 #2
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;
}
예제 #3
0
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);
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
0
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);
	}
}
예제 #8
0
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);
  }
}
예제 #9
0
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;
};
예제 #10
0
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;
}
예제 #11
0
uint8_t RegionFile::getChunkDataCompression(const ChunkPos& chunk) const {
	return chunk_data_compression[getChunkIndex(chunk)];
}
예제 #12
0
const std::vector<uint8_t>& RegionFile::getChunkData(const ChunkPos& chunk) const {
	return chunk_data[getChunkIndex(chunk)];
}
예제 #13
0
void RegionFile::setChunkTimestamp(const ChunkPos& chunk, uint32_t timestamp) {
	chunk_timestamps[getChunkIndex(chunk)] = timestamp;
}
예제 #14
0
int RegionFile::getChunkTimestamp(const ChunkPos& chunk) const {
	return chunk_timestamps[getChunkIndex(chunk)];
}
예제 #15
0
bool RegionFile::hasChunk(const ChunkPos& chunk) const {
	return chunk_exists[getChunkIndex(chunk)];
}
예제 #16
0
 /**
  * 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();
 }