summary refs log tree commit diff
path: root/src/World/World.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/World/World.cpp')
-rw-r--r--src/World/World.cpp69
1 files changed, 54 insertions, 15 deletions
diff --git a/src/World/World.cpp b/src/World/World.cpp
index 7d1b4ee..1782fd4 100644
--- a/src/World/World.cpp
+++ b/src/World/World.cpp
@@ -3,33 +3,55 @@
 namespace MC::World {
 
 std::vector<World::ChunkData> World::get_visible_chunks(Vector<3> position) {
+    auto finished_chunks = load_finished_chunks_from_queue();
     auto visible_chunks = get_visible_chunk_indices(position);
 
-    auto difference = visible_chunks;
+    auto updates = visible_chunks;
     for (auto index : m_visible_chunks) {
-        difference.erase(index);
+        updates.erase(index);
+    }
+    for (auto index : finished_chunks) {
+        updates.insert(index);
     }
 
-    if (!difference.empty()) {
-        for (auto new_index: difference) {
-            auto& data = get_or_generate(new_index);
-            if (!data.mesh.has_value()) {
-                auto mesh = data.chunk->mesh();
-                data.mesh = GFX::Binder::load(mesh);
-            }
-        }
+    if (!updates.empty()) {
+        process_chunk_visibility_updates(updates);
         m_visible_chunks = visible_chunks;
     }
 
     std::vector<World::ChunkData> chunks{};
     chunks.reserve(visible_chunks.size());
     for (auto index : visible_chunks) {
-        chunks.push_back(get_or_generate(index));
+        auto& data = get(index);
+        if (data.status == ChunkStatus::Done) {
+            chunks.push_back(data);
+        }
     }
 
     return chunks;
 }
 
+void World::process_chunk_visibility_updates(std::unordered_set<ChunkIndex>& new_chunks) {
+    for (auto new_index: new_chunks) {
+        auto& data = get(new_index);
+        switch (data.status) {
+            case ChunkStatus::Empty:
+                request_generation(new_index);
+                data.status = ChunkStatus::InFlight;
+                break;
+            case ChunkStatus::InFlight:
+                // Continue waiting...
+                break;
+            case ChunkStatus::Done:
+                if (!data.mesh.has_value()) {
+                    auto mesh = data.chunk.value().mesh();
+                    data.mesh = GFX::Binder::load(mesh);
+                }
+                break;
+        }
+    }
+}
+
 std::unordered_set<ChunkIndex> World::get_visible_chunk_indices(Vector<3> position) const {
     int32_t center_x = std::round(position.x() / Chunk::Width);
     int32_t center_y = std::round(position.z() / Chunk::Width);
@@ -47,11 +69,29 @@ std::unordered_set<ChunkIndex> World::get_visible_chunk_indices(Vector<3> positi
     return indices;
 }
 
-World::ChunkData& World::get_or_generate(ChunkIndex index) {
+std::unordered_set<ChunkIndex> World::load_finished_chunks_from_queue() {
+    std::unordered_set<ChunkIndex> indices;
+    auto results = m_queue.done();
+    for (auto& result : results) {
+        auto& data = get(result.id);
+        data.chunk = {result.res};
+        data.status = ChunkStatus::Done;
+        indices.insert(result.id);
+    }
+
+    return indices;
+}
+
+void World::request_generation(ChunkIndex index) {
+    m_queue.add(index, [=]() {
+        return m_generator.generate(index.x, index.y);
+    });
+}
+
+World::ChunkData& World::get(ChunkIndex index) {
     auto entry = m_chunks.find(index);
     if (entry == m_chunks.end()) {
-        auto chunk = m_generator.generate(index.x, index.y);
-        ChunkData data{index, std::make_shared<Chunk>(chunk)};
+        ChunkData data{index, ChunkStatus::Empty};
 
         m_chunks.insert({index, data});
         return m_chunks.at(index);
@@ -60,5 +100,4 @@ World::ChunkData& World::get_or_generate(ChunkIndex index) {
     return entry->second;
 }
 
-
 }
\ No newline at end of file