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
|
#pragma once
#include "array"
#include "ChunkDimensions.hpp"
#include "../Math/Mod.hpp"
#include "../Math/Random.hpp"
#include "../Math/Vector.hpp"
namespace MC::Position {
#define MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(name, t) \
name() = default; \
template<typename ...Args, std::enable_if_t<sizeof...(Args) == 3, Int> = 0> \
name(Args... args) : Vector{ static_cast<t>(args)... } {} \
name(Vector v) : Vector(v) {}
// Offset between block positions within single chunk.
class BlockLocalOffset : public Vector<3, I16> {
public:
MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(BlockLocalOffset, I16)
Bool fits_within_chunk() const {
using namespace MC::World::ChunkDimensions;
return x() >= 0 && x() < Width && y() >= 0 && y() < Height && z() >= 0 && z() < Width;
}
};
// Position of a block within single chunk.
class BlockLocal : public Vector<3, U8> {
public:
MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(BlockLocal, U8)
BlockLocal(BlockLocalOffset offset) : BlockLocal(offset.x(), offset.y(), offset.z()) {}
BlockLocalOffset offset(BlockLocalOffset by) {
return {
static_cast<I8>(x() + by.x()),
static_cast<I8>(y() + by.y()),
static_cast<I8>(z() + by.z())
};
}
};
// Offset between block positions within entire world.
class BlockWorldOffset : public Vector<3, I64> {
public:
MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(BlockWorldOffset, I64)
};
// Position of a block within entire world.
class BlockWorld : public Vector<3, I64> {
public:
MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(BlockWorld, I64)
BlockLocal to_local() const {
using namespace MC::World::ChunkDimensions;
return {Math::mod(x(), Width), std::clamp<I64>(y(), 0, Height), Math::mod(z(), Width)};
}
};
const std::array<BlockLocalOffset, 6> axis_directions = {{
{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1},
}};
// Offset between two world positions.
class WorldOffset : public Vector<3> {
public:
MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(WorldOffset, Real)
};
// Position within entire world.
class World : public Vector<3> {
public:
MC_POSITION_MAKE_DEFAULT_CONSTRUCTORS(World, Real)
BlockWorld round_to_block() const {
auto rounded = map([](auto x) { return std::floor(x); });
return {rounded.x(), rounded.y(), rounded.z()};
}
};
}
|