Zepha/src/world/DimensionBase.cpp

114 lines
3.7 KiB
C++

//
// Created by aurailus on 2019-11-20.
//
#include "DimensionBase.h"
#include "chunk/Chunk.h"
#include "chunk/Region.h"
#include "chunk/MapBlock.h"
#include "../def/DefinitionAtlas.h"
DimensionBase::DimensionBase(DefinitionAtlas &defs) : defs(defs) {}
std::shared_ptr<Region> DimensionBase::getRegion(glm::ivec3 regionPosition) {
if (!regions.count(regionPosition)) return nullptr;
return regions[regionPosition];
}
void DimensionBase::removeRegion(glm::ivec3 pos) {
regions.erase(pos);
}
std::shared_ptr<MapBlock> DimensionBase::getMapBlock(glm::ivec3 mapBlockPosition) {
auto region = getRegion(Space::Region::world::fromMapBlock(mapBlockPosition));
if (!region) return nullptr;
return (*region)[Space::MapBlock::index(mapBlockPosition)];
}
void DimensionBase::removeMapBlock(glm::ivec3 pos) {
auto region = getRegion(Space::Region::world::fromMapBlock(pos));
if (!region) return;
auto ind = Space::MapBlock::index(pos);
region->remove(ind);
if (region->count == 0) removeRegion(Space::Region::world::fromMapBlock(pos));
}
bool DimensionBase::mapBlockGenerated(glm::ivec3 mapBlockPosition) {
auto mb = getMapBlock(mapBlockPosition);
return mb && mb->generated;
}
std::shared_ptr<Chunk> DimensionBase::getChunk(glm::ivec3 chunkPosition) {
auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(chunkPosition));
if (!mapBlock) return nullptr;
return (*mapBlock)[Space::Chunk::index(chunkPosition)];
}
void DimensionBase::setChunk(std::shared_ptr<Chunk> chunk) {
auto mapBlock = getOrCreateMapBlock(Space::MapBlock::world::fromChunk(chunk->pos));
mapBlock->set(Space::Chunk::index(chunk->pos), chunk);
}
void DimensionBase::removeChunk(glm::ivec3 pos){
auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(pos));
if (!mapBlock) return;
auto ind = Space::Chunk::index(pos);
mapBlock->remove(ind);
if (mapBlock->count == 0) removeMapBlock(Space::MapBlock::world::fromChunk(pos));
}
unsigned int DimensionBase::getBlock(glm::ivec3 pos) {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (!chunk) return 0;
auto l = chunk->aquireLock();
return chunk->getBlock(Space::Block::relative::toChunk(pos));
}
bool DimensionBase::setBlock(glm::ivec3 pos, unsigned int block) {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (!chunk) return false;
auto l = chunk->aquireLock();
auto &def = defs.blockFromId(block);
return chunk->setBlock(Space::Block::relative::toChunk(pos), block);
}
std::shared_ptr<Region> DimensionBase::getOrCreateRegion(glm::ivec3 pos) {
if (regions[pos]) return regions[pos];
regions[pos] = std::make_shared<Region>(pos);
return regions[pos];
}
std::shared_ptr<MapBlock> DimensionBase::getOrCreateMapBlock(glm::ivec3 mapBlockPosition) {
auto region = getOrCreateRegion(Space::Region::world::fromMapBlock(mapBlockPosition));
unsigned int index = Space::MapBlock::index(mapBlockPosition);
if ((*region)[index] != nullptr) return (*region)[index];
region->set(index, std::make_shared<MapBlock>(mapBlockPosition));
return (*region)[index];
}
std::shared_ptr<Chunk> DimensionBase::combinePartials(std::shared_ptr<Chunk> a, std::shared_ptr<Chunk> b) {
std::shared_ptr<Chunk> src;
std::shared_ptr<Chunk> res;
if (a->generated) {
res = a;
src = b;
}
else {
res = b;
src = a;
}
for (unsigned int i = 0; i < 4096; i++) {
if (src->getBlock(i) > DefinitionAtlas::INVALID) res->setBlock(i, src->getBlock(i));
}
res->generated = src->generated || res->generated;
res->partial = !res->generated;
res->countRenderableBlocks();
return res;
}