1
0
Fork 0
Univerxel/src/world/Area.hpp

75 lines
2.6 KiB
C++

#pragma once
#include "forward.h"
#include <shared_mutex_guarded.h>
using namespace libguarded;
#include "region/index.hpp"
#include "Generator.hpp"
#include "../data/geometry/IBox.hpp"
namespace world {
/// Chunk map with restricted access
struct ChunkContainer: robin_hood::unordered_map<chunk_pos, std::shared_ptr<Chunk>> {
private:
int radius;
public:
/// Area radius in chunks
constexpr inline int getRadius() const { return radius; }
ChunkContainer(int radius): radius(radius) {
assert(radius > 0 && radius < (1 << 22) / CHUNK_LENGTH);
}
inline bool inRange(const chunk_pos& pos) const {
return glm::abs(pos.x) < radius && glm::abs(pos.y) < radius && glm::abs(pos.z) < radius;
}
std::optional<std::shared_ptr<Chunk>> findInRange(const chunk_pos &pos) const;
std::optional<std::shared_ptr<const Chunk>> findOrEmpty(const chunk_pos &pos) const;
};
/// Area (aka big group of chunks)
struct Area {
public:
using regions_t = robin_hood::unordered_map<region_pos, std::shared_ptr<Region>>;
struct params {
voxel_pos center;
int radius;
int seed = 42;
};
/// radius: size in chunk (length = radius * 2 + 1)
Area(const params& p): center(p.center), chunks(p.radius), generator(p.seed) { }
inline const area_pos &getOffset() const { return center; }
inline geometry::IBox getBounding() const {
const auto c = center.as_voxel();
return geometry::IBox(c - voxel_pos(CHUNK_LENGTH * (chunks.getRadius() - 1)),
c + voxel_pos(CHUNK_LENGTH * chunks.getRadius()));
}
/// Move offset return if chunk_change
bool inline move(const area_pos::offset_t &offset) {
const auto prev = glm::divide(center.as_voxel());
center = center + offset;
return prev != glm::divide(center.as_voxel());
}
inline const ChunkContainer &getChunks() const { return chunks; }
inline ChunkContainer &setChunks() { return chunks; }
std::shared_ptr<Region> getRegion(const std::string& folderPath, const area_<region_pos> &);
shared_guarded<regions_t>::handle getRegions() { return regions.lock(); }
inline Generator &getGenerator() { return generator; }
inline params getParams() const { return params{center.as_voxel(), chunks.getRadius(), generator.getSeed()}; }
private:
area_pos center;
//TODO: rotation
ChunkContainer chunks;
shared_guarded<regions_t> regions;
Generator generator;
};
}