summary refs log tree commit diff
path: root/src/World/World.hpp
blob: 82741b0fa23570ec6e7aa5f63561f9f7b2ea6690 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#pragma once

#include "Generation/Generator.hpp"
#include "ChunkIndex.hpp"
#include "ChunkRegistry.hpp"
#include "../Compute/Queue.hpp"
#include "../Math/Ray.hpp"
#include "Generation/ChunkMeshing.hpp"
#include "Generation/Lighting.hpp"
#include "VoxelTraversal.hpp"

namespace MC::World {

class World {
public:
    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);
    void break_block(Position::BlockWorld pos);

    using TraversalResult = VoxelTraversal::TraversalResult;

    template <typename F>
    TraversalResult traverse(Ray ray, F&& predicate, Real max_distance = 0) {
        return VoxelTraversal::traverse(
            ray,
            [this, &predicate](Position::BlockWorld pos) { return predicate(block_at(pos)); },
            max_distance
        );
    }

    Real get_average_chunk_time() const;

    ChunkRegistry& chunks() { return m_registry; }
private:
    std::vector<ChunkIndex> get_visible_chunk_indices(Position::World position) const;

    void process_chunk_updates(Time const& time);
    void request_generation(ChunkIndex index, Real priority);
    void request_reification(ChunkIndex index, Real priority);

    Bool should_reassess_priorities(Position::World player_position) const;
    void reassess_priorities(Position::World player_position);

    enum class RequestType { Initial, Update };
    static Real calculate_priority(ChunkIndex chunk, Position::World player_position, RequestType request_type);

    void log_chunk_time(U64 chunk_time_ms);

    U8 m_view_distance_radius = 10;

    Bool is_chunk_in_radius(Position::World position, ChunkIndex chunk) const;

    struct GenerationResult {
        Chunk chunk;
        U64 generation_duration;
    };
    using GenerationQueue = Compute::Queue<GenerationResult, ChunkIndex>;
    GenerationQueue m_generation_queue{1};

    struct ReificationResult {
        Generation::ChunkMeshing::ChunkMesh chunk_mesh;
    };
    using ReificationQueue = Compute::Queue<ReificationResult, ChunkIndex>;
    ReificationQueue m_reification_queue{1};

    Real m_priority_reassession_distance_threshold = 50;
    Position::World m_last_priority_reassession_at = {};

    Generation::Generator m_generator;
    Generation::Lighting m_lighting;
    ChunkRegistry m_registry;

    struct Statistics {
        UInt chunk_time_sample_count;
        Real average_chunk_time_ms;
    };
    Statistics m_statistics{0, 0.0f};
};

}