diff options
Diffstat (limited to 'src/world.cpp')
| -rw-r--r-- | src/world.cpp | 94 |
1 files changed, 84 insertions, 10 deletions
diff --git a/src/world.cpp b/src/world.cpp index 63209bf7..56025587 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -1,19 +1,93 @@ #include "world.hpp" +#include "chunk.hpp" namespace floormat { -static_assert(sizeof(decltype(local_coords::x))*8 == 8); -static_assert(sizeof(decltype(chunk_coords::x))*8 == 16); -static_assert(std::is_same_v<decltype(local_coords::x), decltype(local_coords::y)>); -static_assert(std::is_same_v<decltype(chunk_coords::x), decltype(chunk_coords::y)>); +struct chunk_pointer_maker final +{ + operator std::shared_ptr<chunk>() const { return std::make_shared<chunk>(); } +}; -static_assert(std::is_same_v<decltype(chunk_coords::x), decltype(chunk_coords::y)>); +world::world() +{ + _chunks.max_load_factor(max_load_factor); +} -static_assert(global_coords{{-1, -1}, {}} != global_coords{}); -static_assert(global_coords{15, 15}.chunk() == global_coords{}.chunk()); -static_assert(global_coords{15, 16}.chunk() != global_coords{}.chunk()); -static_assert(global_coords{(1 + (1<<15)) << 4 | 3, (2 + (1<<15)) << 4 | 4} == global_coords{{1, 2}, {3, 4}}); +std::shared_ptr<chunk> world::operator[](chunk_coords c) noexcept +{ + auto [it, inserted] = _chunks.try_emplace(c, chunk_pointer_maker{}); + maybe_collect(); return it->second; +} +std::shared_ptr<const chunk> world::maybe_chunk(chunk_coords c) const noexcept +{ + if (const auto it = _chunks.find(c); it != _chunks.cend()) + return it->second; + else + return nullptr; +} -} // namespace floormat +std::shared_ptr<chunk> world::maybe_chunk(chunk_coords c) noexcept +{ + return std::const_pointer_cast<chunk>(const_cast<const world&>(*this).maybe_chunk(c)); +} + +bool world::contains(chunk_coords c) const noexcept +{ + return _chunks.find(c) != _chunks.cend(); +} + +void world::clear() +{ + _last_collection = 0; + _chunks.rehash(initial_capacity); +} + +void world::maybe_collect() +{ + if (_last_collection + collect_every > _chunks.size()) + collect(); +} + +void world::collect() +{ + for (auto it = _chunks.begin(); it != _chunks.end(); (void)0) + { + const auto& [k, c] = *it; + if (c->empty()) + it = _chunks.erase(it); + else + it++; + } + _last_collection = _chunks.size(); +} +std::size_t world::hasher::operator()(chunk_coords c) const noexcept +{ + void _really_unreachable(); + + std::size_t x = (std::size_t)c.y << 16 | (std::size_t)c.x; + if constexpr(sizeof(std::size_t) == 4) + { + // by Chris Wellons <https://nullprogram.com/blog/2018/07/31/> + x ^= x >> 15; + x *= 0x2c1b3c6dU; + x ^= x >> 12; + x *= 0x297a2d39U; + x ^= x >> 15; + } + else if constexpr(sizeof(std::size_t) == 8) + { + x ^= x >> 30; + x *= 0xbf58476d1ce4e5b9U; + x ^= x >> 27; + x *= 0x94d049bb133111ebU; + x ^= x >> 31; + } + else + _really_unreachable(); + + return x; +} + +} // namespace floormat |
