#pragma once #include "compat/int-hash.hpp" #include "compat/integer-types.hpp" #include "chunk.hpp" #include "global-coords.hpp" #include #include namespace floormat { struct world final { private: struct chunk_tuple final { static constexpr chunk_coords invalid_coords = { -1 << 15, -1 << 15 }; chunk* c = nullptr; chunk_coords pos = invalid_coords; } _last_chunk; void maybe_collect(); static constexpr std::size_t initial_capacity = 64, collect_every = 64; static constexpr float max_load_factor = .5; static constexpr auto hasher = [](chunk_coords c) constexpr -> std::size_t { return int_hash((std::size_t)c.y << 16 | (std::size_t)c.x); }; std::unordered_map _chunks; std::size_t _last_collection = 0; explicit world(std::size_t capacity); public: explicit world(); struct pair final { chunk& c; tile_ref t; }; // NOLINT template explicit world(std::unordered_map&& chunks); chunk& operator[](chunk_coords c) noexcept; pair operator[](global_coords pt) noexcept; bool contains(chunk_coords c) const noexcept; void clear(); void collect(bool force = false); std::size_t size() const noexcept { return _chunks.size(); } [[deprecated]] const auto& chunks() const noexcept { return _chunks; } // only for serialization void serialize(StringView filename); static world deserialize(StringView filename); fm_DECLARE_DEPRECATED_COPY_ASSIGNMENT(world); fm_DECLARE_DEFAULT_MOVE_ASSIGNMENT_(world); }; template world::world(std::unordered_map&& chunks) : world{std::max(initial_capacity, std::size_t(1/max_load_factor * 2 * chunks.size()))} { for (auto&& [coord, c] : chunks) operator[](coord) = std::move(c); } } // namespace floormat