summaryrefslogtreecommitdiffhomepage
path: root/src/world.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/world.cpp')
-rw-r--r--src/world.cpp94
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