From 6a30c3e4f22de4d0f8f32107f614f597f5f39cc1 Mon Sep 17 00:00:00 2001 From: Mel Date: Mon, 12 Feb 2024 13:01:15 +0100 Subject: Rescue player from void if current chunk wasn't generated prior --- src/Entities/Player.cpp | 16 ++++++++++++++++ src/Entities/Player.hpp | 2 ++ src/Time.cpp | 4 ++++ src/Time.hpp | 2 ++ src/World/ChunkRegistry.hpp | 6 ++++++ src/World/World.cpp | 25 +++++++++++++------------ src/World/World.hpp | 11 +++++------ 7 files changed, 48 insertions(+), 18 deletions(-) (limited to 'src') 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 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 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 #include +#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 = {}; std::optional land_mesh = {}; std::optional 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 World::get_visible_chunks(Position::World position) { - process_chunk_updates(); +std::vector 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 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 get_visible_chunks(Position::World position); + std::vector 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 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; - GenerationQueue m_generation_queue{4}; + GenerationQueue m_generation_queue{1}; struct ReificationResult { - Chunk chunk; Generation::ChunkMeshing::ChunkMesh chunk_mesh; }; using ReificationQueue = Compute::Queue; - ReificationQueue m_reification_queue{4}; + ReificationQueue m_reification_queue{1}; Real m_priority_reassession_distance_threshold = 50; Position::World m_last_priority_reassession_at = {}; -- cgit 1.4.1