diff options
| author | Mel <einebeere@gmail.com> | 2023-08-03 02:29:44 +0200 |
|---|---|---|
| committer | Mel <einebeere@gmail.com> | 2023-08-03 02:31:12 +0200 |
| commit | 1d574e5e8fe3f08d13f1b8c4444fc4cb02cf0faf (patch) | |
| tree | d151baab68d6aa444a5968a1b579c5d48025084e /src/World/World.cpp | |
| parent | 15352db7bc03a176ea7a184f40a7f4e72b54b5fe (diff) | |
| download | meowcraft-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.cpp | 42 |
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; +} + } |
