summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Entities/Player.cpp16
-rw-r--r--src/Entities/Player.hpp2
-rw-r--r--src/Time.cpp4
-rw-r--r--src/Time.hpp2
-rw-r--r--src/World/ChunkRegistry.hpp6
-rw-r--r--src/World/World.cpp25
-rw-r--r--src/World/World.hpp11
7 files changed, 48 insertions, 18 deletions
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 652f3fd..7a1c1af 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -10,6 +10,9 @@ void Player::update(const Time& time, GFX::Window& window, GFX::Camera& camera,
     auto destination = movement(window, time, input_direction);
 
     if (can_collide()) {
+        if (m_velocity.y() < 0.0)
+            destination = rescue_from_void_on_new_chunk(time, world, destination);
+
         auto const [position, blocked_axes] = process_collisions(world, m_transform.position(), destination);
 
         destination = position;
@@ -286,6 +289,19 @@ std::vector<AABB> Player::terrain_collision_domain(
     return colliding_blocks;
 }
 
+Position::World Player::rescue_from_void_on_new_chunk(Time const& time, World::World& world, Position::World position) {
+    auto& chunk = world.chunks().get(World::ChunkIndex::from_position(position));
+    // If the chunk was generated at the previous tick, we
+    // can rescue the player by moving them to the top of the chunk.
+    if (chunk.generated() && chunk.generated_at_tick == time.tick() - 1){
+        // TODO: Move to first solid block.
+        position.y() = World::Chunk::Height / 2.0;
+        m_transform.position() = position;
+        m_velocity.y() = 0;
+    }
+    return position;
+}
+
 Transform Player::camera_transform() const {
     auto position = m_transform.position();
     position.y() += 1.5;
diff --git a/src/Entities/Player.hpp b/src/Entities/Player.hpp
index 83ac091..2b69d57 100644
--- a/src/Entities/Player.hpp
+++ b/src/Entities/Player.hpp
@@ -43,6 +43,8 @@ private:
     static ProcessCollisionsResult process_collisions(World::World& world, Position::World from, Position::World to);
     static std::vector<AABB> terrain_collision_domain(Position::World from, Position::World to, World::World& world);
 
+    Position::World rescue_from_void_on_new_chunk(Time const& time, World::World& world, Position::World position);
+
     Position::World movement(GFX::Window& window, const Time& time, Vec3 input_direction);
     Vec3 walking_velocity(GFX::Window& window, const Time& time, Vec3 input_direction);
     Vec3 flying_velocity(GFX::Window& window, const Time& time, Vec3 input_direction);
diff --git a/src/Time.cpp b/src/Time.cpp
index 7f59250..e459374 100644
--- a/src/Time.cpp
+++ b/src/Time.cpp
@@ -20,6 +20,10 @@ U64 Time::total_frames() const {
     return m_total_frames;
 }
 
+Time::Tick Time::tick() const {
+    return total_frames();
+}
+
 Real Time::delta() const {
     return m_delta;
 }
diff --git a/src/Time.hpp b/src/Time.hpp
index 83c41c0..04f22c8 100644
--- a/src/Time.hpp
+++ b/src/Time.hpp
@@ -7,6 +7,7 @@ namespace MC {
 class Time {
 public:
     using Timestamp = U64;
+    using Tick = U64;
 
     Time() = default;
 
@@ -14,6 +15,7 @@ public:
     void end_frame();
 
     U64 total_frames() const;
+    Tick tick() const;
     Real delta() const;
 
     static Timestamp now();
diff --git a/src/World/ChunkRegistry.hpp b/src/World/ChunkRegistry.hpp
index 2b87a3a..d583765 100644
--- a/src/World/ChunkRegistry.hpp
+++ b/src/World/ChunkRegistry.hpp
@@ -2,6 +2,7 @@
 
 #include <optional>
 #include <unordered_map>
+#include "../Time.hpp"
 #include "Chunk.hpp"
 #include "ChunkIndex.hpp"
 #include "Position.hpp"
@@ -23,11 +24,16 @@ public:
     struct Data {
         ChunkIndex index;
         Status status;
+        Time::Tick generated_at_tick;
         std::optional<Chunk> chunk = {};
 
         std::optional<GFX::Mesh> land_mesh = {};
         std::optional<GFX::Mesh> water_mesh = {};
 
+        Bool generated() const {
+            return chunk.has_value();
+        }
+
         Status get_status() const {
             if (status == Status::Done && chunk.value().is_damaged()) { return Status::Damaged; }
             return status;
diff --git a/src/World/World.cpp b/src/World/World.cpp
index 2b5848b..b5dae43 100644
--- a/src/World/World.cpp
+++ b/src/World/World.cpp
@@ -5,8 +5,8 @@
 
 namespace MC::World {
 
-std::vector<ChunkRegistry::Data*> World::get_visible_chunks(Position::World position) {
-    process_chunk_updates();
+std::vector<ChunkRegistry::Data*> World::get_visible_chunks(Time const& time, Position::World position) {
+    process_chunk_updates(time);
 
     if (should_reassess_priorities(position)) {
         reassess_priorities(position);
@@ -84,22 +84,24 @@ std::vector<ChunkIndex> World::get_visible_chunk_indices(const Position::World p
     return indices;
 }
 
-void World::process_chunk_updates() {
+void World::process_chunk_updates(Time const& time) {
     auto generation_results = m_generation_queue.done();
     for (auto& [id, res] : generation_results) {
-        m_registry.get(id) = {id, ChunkRegistry::Status::NeedsReification, {res.chunk}};
+        m_registry.get(id) = {
+            id, ChunkRegistry::Status::NeedsReification,
+            time.tick(),
+            {res.chunk}
+        };
 
         log_chunk_time(res.generation_duration);
     }
 
     auto reification_results = m_reification_queue.done();
     for (auto& [id, res] : reification_results) {
-        m_registry.get(id) = {
-            id, ChunkRegistry::Status::Done,
-            {res.chunk},
-            res.chunk_mesh.land_mesh,
-            res.chunk_mesh.water_mesh
-        };
+        auto& data = m_registry.get(id);
+        data.status = ChunkRegistry::Status::Done;
+        data.land_mesh = res.chunk_mesh.land_mesh;
+        data.water_mesh = res.chunk_mesh.water_mesh;
 
         // TODO: Damage surrounding chunks.
     }
@@ -124,8 +126,7 @@ void World::request_reification(ChunkIndex index, Real priority) {
         intitial_lighting.add_chunk(chunk);
         intitial_lighting.illuminate(chunk);
 
-        auto meshes = Generation::ChunkMeshing::mesh_chunk(chunk, meshing_context);
-        return {chunk, meshes};
+        return {Generation::ChunkMeshing::mesh_chunk(chunk, meshing_context)};
     });
 }
 
diff --git a/src/World/World.hpp b/src/World/World.hpp
index 76005da..82741b0 100644
--- a/src/World/World.hpp
+++ b/src/World/World.hpp
@@ -13,7 +13,7 @@ namespace MC::World {
 
 class World {
 public:
-    std::vector<ChunkRegistry::Data*> get_visible_chunks(Position::World position);
+    std::vector<ChunkRegistry::Data*> get_visible_chunks(Time const& time, Position::World position);
 
     Chunk::BlockData block_at(Position::BlockWorld pos);
     void set_block(Position::BlockWorld pos, BlockType type);
@@ -36,7 +36,7 @@ public:
 private:
     std::vector<ChunkIndex> get_visible_chunk_indices(Position::World position) const;
 
-    void process_chunk_updates();
+    void process_chunk_updates(Time const& time);
     void request_generation(ChunkIndex index, Real priority);
     void request_reification(ChunkIndex index, Real priority);
 
@@ -48,7 +48,7 @@ private:
 
     void log_chunk_time(U64 chunk_time_ms);
 
-    U8 m_view_distance_radius = 12;
+    U8 m_view_distance_radius = 10;
 
     Bool is_chunk_in_radius(Position::World position, ChunkIndex chunk) const;
 
@@ -57,14 +57,13 @@ private:
         U64 generation_duration;
     };
     using GenerationQueue = Compute::Queue<GenerationResult, ChunkIndex>;
-    GenerationQueue m_generation_queue{4};
+    GenerationQueue m_generation_queue{1};
 
     struct ReificationResult {
-        Chunk chunk;
         Generation::ChunkMeshing::ChunkMesh chunk_mesh;
     };
     using ReificationQueue = Compute::Queue<ReificationResult, ChunkIndex>;
-    ReificationQueue m_reification_queue{4};
+    ReificationQueue m_reification_queue{1};
 
     Real m_priority_reassession_distance_threshold = 50;
     Position::World m_last_priority_reassession_at = {};