summaryrefslogtreecommitdiffhomepage
path: root/src/chunk.hpp
blob: 9f4e2ebdc147793dd210d446e27085ac042b802e (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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#pragma once
#include "tile.hpp"
#include "tile-iterator.hpp"
#include "scenery.hpp"
#include <type_traits>
#include <array>
#include <memory>
#include <Magnum/GL/Mesh.h>
#include "RTree.h"

namespace floormat {

struct anim_atlas;
struct entity;

enum class collision : std::uint8_t {
    view, shoot, move,
};

enum class collision_type : std::uint8_t {
    none, entity, scenery, geometry,
};

struct collision_data final {
    std::uint64_t tag       : 2;
    std::uint64_t pass      : 2;
    std::uint64_t data      : 60;
};

struct chunk final
{
    friend struct tile_ref;
    friend struct entity;
    friend struct world;

    tile_ref operator[](std::size_t idx) noexcept;
    tile_proto operator[](std::size_t idx) const noexcept;
    tile_ref operator[](local_coords xy) noexcept;
    tile_proto operator[](local_coords xy) const noexcept;

    using iterator = tile_iterator;
    using const_iterator = tile_const_iterator;

    iterator begin() noexcept;
    iterator end() noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;
    const_iterator begin() const noexcept;
    const_iterator end() const noexcept;

    bool empty(bool force = false) const noexcept;

    chunk() noexcept;
    ~chunk() noexcept;
    chunk(const chunk&) = delete;
    chunk& operator=(const chunk&) = delete;
    chunk(chunk&&) noexcept;
    chunk& operator=(chunk&&) noexcept;

    void mark_ground_modified() noexcept;
    void mark_walls_modified() noexcept;
    void mark_scenery_modified(bool collision_too = true) noexcept;
    void mark_passability_modified() noexcept;
    void mark_modified() noexcept;

    bool is_passability_modified() const noexcept;
    bool is_scenery_modified() const noexcept;

    struct ground_mesh_tuple final {
        GL::Mesh& mesh;
        const ArrayView<const std::uint8_t> ids;
        const std::size_t size;
    };
    struct wall_mesh_tuple final {
        GL::Mesh& mesh;
        const ArrayView<const std::uint16_t> ids;
        const std::size_t size;
    };

    struct scenery_mesh_tuple final {
        GL::Mesh& mesh;
    };

    struct vertex {
        Vector3 position;
        Vector2 texcoords;
        float depth = -1;
    };

    ground_mesh_tuple ensure_ground_mesh() noexcept;
    tile_atlas* ground_atlas_at(std::size_t i) const noexcept;

    wall_mesh_tuple ensure_wall_mesh() noexcept;
    tile_atlas* wall_atlas_at(std::size_t i) const noexcept;

    scenery_mesh_tuple ensure_scenery_mesh() noexcept;

    void ensure_passability() noexcept;

    using RTree = ::RTree<std::uint64_t, float, 2, float>;

    const RTree* rtree() const noexcept;
    RTree* rtree() noexcept;

    template<typename F>
    requires requires(F fun) { fun(); }
    void with_scenery_update(entity& e, F&& fun);

    using entity_vector = std::vector<std::shared_ptr<entity>>;
    using entity_const_iterator = typename entity_vector::const_iterator;

    [[nodiscard]] bool can_place_entity(const entity_proto& proto, local_coords pos);

    void add_entity(const std::shared_ptr<entity>& e);
    void add_entity_unsorted(const std::shared_ptr<entity>& e);
    void sort_entities();
    void remove_entity(entity_const_iterator it);
    const std::vector<std::shared_ptr<entity>>& entities() const;

private:
    std::array<std::shared_ptr<tile_atlas>, TILE_COUNT> _ground_atlases;
    std::array<std::uint8_t, TILE_COUNT> ground_indexes = {};
    std::array<variant_t, TILE_COUNT> _ground_variants = {};
    std::array<std::shared_ptr<tile_atlas>, TILE_COUNT*2> _wall_atlases;
    std::array<std::uint16_t, TILE_COUNT*2> wall_indexes = {};
    std::array<variant_t, TILE_COUNT*2> _wall_variants = {};
    std::vector<std::shared_ptr<entity>> _entities;

    std::vector<std::array<UnsignedShort, 6>> scenery_indexes;
    std::vector<std::array<vertex, 4>> scenery_vertexes;

    GL::Mesh ground_mesh{NoCreate}, wall_mesh{NoCreate}, scenery_mesh{NoCreate};

    RTree _rtree;

    mutable bool _maybe_empty      : 1 = true,
                 _ground_modified  : 1 = true,
                 _walls_modified   : 1 = true,
                 _scenery_modified : 1 = true,
                 _pass_modified    : 1 = true,
                 _teardown         : 1 = false;

    struct bbox final // NOLINT(cppcoreguidelines-pro-type-member-init)
    {
        std::uint64_t id;
        Vector2i start, end;

        bool operator==(const bbox& other) const noexcept;
    };
    bool _bbox_for_scenery(const entity& s, bbox& value) noexcept;
    void _remove_bbox(const bbox& x);
    void _add_bbox(const bbox& x);
    void _replace_bbox(const bbox& x0, const bbox& x, bool b0, bool b);
};

} // namespace floormat