-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathworld.cpp
More file actions
89 lines (80 loc) · 3.42 KB
/
world.cpp
File metadata and controls
89 lines (80 loc) · 3.42 KB
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
#include "world.hpp"
#include "network.hpp"
ChunkData generate(IndexId id) {
ChunkData data;
data.id = id;
for (size_t ix = 0; ix < sizex; ix ++) {
for (size_t iy = 0; iy < sizey; iy ++) {
for (size_t iz = 0; iz < sizez; iz ++) {
Block b = Air;
float h = sin(ix*.2) * sin(iz*.3);
if (iy < h*5+20) b = Stone;
if (ix == 0 && iz == 0) b = Grass;
data.blocks[ix][iy][iz] = b;
}
}
}
return data;
}
void World::reload_check(IndexId pos) {
constexpr int render_dist = 2;
for (int cx = -render_dist; cx < render_dist; cx ++) {
for (int cz = -render_dist; cz < render_dist; cz ++) {
IndexId nid(pos.x+cx, pos.y+0, pos.z+cz);
auto already_exists = std::ranges::any_of(live_chunks, [nid](LiveChunk const& chunk) {
return nid == chunk.block_data.id;
});
if (already_exists) continue;
// Generate a new chunk from local data
std::lock_guard<std::mutex> lock(localchunk_guard);
auto lc = lcchunk.find(nid);
if (lc == lcchunk.end()) {
// Make Network Request
net::ClientSection section;
section.kind = net::ClientSectionKind::kClientGetChunkFull;
section.d.c_g_full = net::ClientGetChunkFull(nid);
net::enqueue_section(section);
continue; // Cannot Load Chunk Yet
}
lock.~lock_guard();
auto& cd = lc->second;
LiveChunk chunky(cd);
chunky.position.x = static_cast<float>(cd.id.x) * static_cast<float>(sizex) * blocksize;
chunky.position.y = static_cast<float>(cd.id.y) * static_cast<float>(sizey) * blocksize;
chunky.position.z = static_cast<float>(cd.id.z) * static_cast<float>(sizez) * blocksize;
live_chunks.emplace_back(std::move(chunky));
// Mark Neighbrs to recompute their own meshes
auto neighbors = find_neighbors(nid);
std::ranges::for_each(neighbors, [](std::optional<LiveChunk*> neighbor) {
if (neighbor.has_value()) neighbor.value()->dirty = true;
});
}
}
}
void World::dirty_check() {
auto location = std::ranges::find_if(live_chunks, [](LiveChunk const& c){
return c.dirty;
});
if (location == live_chunks.end()) return;
auto& c = *location;
auto [north, west, south, east, up, down] = find_neighbors(c.block_data.id);
recompute_mesh(c, north, west, south, east, up, down);
}
std::optional<LiveChunk*> World::find_by_id(IndexId id) {
auto location = std::ranges::find_if(this->live_chunks,
[id](LiveChunk const& chunk) {
return chunk.block_data.id == id;
});
if (location == live_chunks.end()) return std::nullopt;
return &(*location);
}
std::array<std::optional<LiveChunk*>, 6> World::find_neighbors(IndexId id) {
auto posid = id;
auto north = find_by_id(IndexId(posid.x, posid.y, posid.z-1));
auto west = find_by_id(IndexId(posid.x-1, posid.y, posid.z));
auto south = find_by_id(IndexId(posid.x, posid.y, posid.z+1));
auto east = find_by_id(IndexId(posid.x+1, posid.y, posid.z));
auto up = find_by_id(IndexId(posid.x, posid.y+1, posid.z));
auto down = find_by_id(IndexId(posid.x, posid.y-1, posid.z));
return {north, west, south, east, up, down};
}