summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2024-02-12 13:01:15 +0100
committerMel <einebeere@gmail.com>2024-02-12 13:01:15 +0100
commit6a30c3e4f22de4d0f8f32107f614f597f5f39cc1 (patch)
treea4e45ac6c5c728266eef1b42099494854744d497
parentd2b5fc5b3bc648afffa42375706429685ac63794 (diff)
downloadmeowcraft-6a30c3e4f22de4d0f8f32107f614f597f5f39cc1.tar.zst
meowcraft-6a30c3e4f22de4d0f8f32107f614f597f5f39cc1.zip
Rescue player from void if current chunk wasn't generated prior
-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 = {};