summary refs log tree commit diff
path: root/src/World/World.cpp
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2023-08-03 02:29:44 +0200
committerMel <einebeere@gmail.com>2023-08-03 02:31:12 +0200
commit1d574e5e8fe3f08d13f1b8c4444fc4cb02cf0faf (patch)
treed151baab68d6aa444a5968a1b579c5d48025084e /src/World/World.cpp
parent15352db7bc03a176ea7a184f40a7f4e72b54b5fe (diff)
downloadmeowcraft-1d574e5e8fe3f08d13f1b8c4444fc4cb02cf0faf.tar.zst
meowcraft-1d574e5e8fe3f08d13f1b8c4444fc4cb02cf0faf.zip
World can now reassess chunk generation priorities on player movement and cancel no longer needed jobs
Diffstat (limited to 'src/World/World.cpp')
-rw-r--r--src/World/World.cpp42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/World/World.cpp b/src/World/World.cpp
index 3d273bd..0f83310 100644
--- a/src/World/World.cpp
+++ b/src/World/World.cpp
@@ -8,6 +8,10 @@ namespace MC::World {
 std::vector<ChunkRegistry::Data*> World::get_visible_chunks(Position::World position) {
     process_chunk_updates();
 
+    if (should_reassess_priorities(position)) {
+        reassess_priorities(position);
+    }
+
     auto visible_chunks = get_visible_chunk_indices(position);
 
     std::vector<ChunkRegistry::Data*> chunks{};
@@ -47,6 +51,8 @@ std::vector<ChunkIndex> World::get_visible_chunk_indices(const Position::World p
     for (I32 x = -radius; x <= radius; x++) {
         I32 height = std::round(std::sqrt(radius * radius - x * x) + 0.5);
         for (I32 y = -height; y <= height; y++) {
+            // Needed so that this function and is_chunk_in_radius forcibly agree.
+            if (!is_chunk_in_radius(position, {x + center_x, y + center_y})) continue;
             indices.emplace_back(x + center_x, y + center_y);
         }
     }
@@ -104,6 +110,33 @@ void World::request_reification(ChunkIndex index, Real priority) {
     });
 }
 
+Bool World::should_reassess_priorities(Position::World player_position) const {
+    return player_position.distance(m_last_priority_reassession_at) > m_priority_reassession_distance_threshold;
+}
+
+void World::reassess_priorities(Position::World player_position) {
+    m_last_priority_reassession_at = player_position;
+
+    // TODO: How do we know a chunk has been requested as an update?
+    m_generation_queue.reassess([&](ChunkIndex id) -> GenerationQueue::Reassession {
+        if (!is_chunk_in_radius(player_position, id)) return {GenerationQueue::Reassession::Cancel};
+
+        return {
+            GenerationQueue::Reassession::Reassess,
+            calculate_priority(id, player_position, RequestType::Initial)
+        };
+    });
+
+    m_reification_queue.reassess([&](ChunkIndex id) -> ReificationQueue::Reassession {
+        if (!is_chunk_in_radius(player_position, id)) return {ReificationQueue::Reassession::Cancel};
+
+        return {
+            ReificationQueue::Reassession::Reassess,
+            calculate_priority(id, player_position, RequestType::Initial)
+        };
+    });
+}
+
 Real World::calculate_priority(ChunkIndex chunk, Position::World player_position, RequestType request_type) {
     auto chunk_position = chunk.middle();
     auto flat_distance = Position::World{player_position.x(), chunk_position.y(), player_position.z()}.distance(chunk_position);
@@ -126,4 +159,13 @@ Real World::get_average_chunk_time() const {
     return m_statistics.average_chunk_time_ms;
 }
 
+Bool World::is_chunk_in_radius(Position::World position, ChunkIndex chunk) const {
+    Real max_distance = (m_view_distance_radius + 2) * Chunk::Width; // TODO: Tune this so that m_view_distance_radius represents the exact radius.
+    auto chunk_position = chunk.middle();
+    // TODO: Create a flat() method in Position::World for things like this. See also: priorities.
+    Position::World flat_position{position.x(), chunk_position.y(), position.z()};
+
+    return chunk_position.distance(flat_position) < max_distance;
+}
+
 }