summary refs log tree commit diff
path: root/src/World/Position.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/World/Position.hpp')
-rw-r--r--src/World/Position.hpp66
1 files changed, 49 insertions, 17 deletions
diff --git a/src/World/Position.hpp b/src/World/Position.hpp
index 07de6f3..bc874c0 100644
--- a/src/World/Position.hpp
+++ b/src/World/Position.hpp
@@ -2,38 +2,36 @@
 
 #include "array"
 #include "ChunkDimensions.hpp"
+#include "../Math/Mod.hpp"
+#include "../Math/Random.hpp"
 #include "../Math/Vector.hpp"
 
 namespace MC::Position {
 
-// Position within entire world.
-using World = Vector<3>;
-
-// Offset between two world positions.
-using WorldOffset = Vector<3>;
+#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 BlockOffset : public Vector<3, I16> {
+class BlockLocalOffset : public Vector<3, I16> {
 public:
-    BlockOffset(I16 x, I16 y, I16 z) : Vector(x, y, z) {}
+    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 entire world.
-class BlockWorld : public Vector<3, I64> {
-public:
-    BlockWorld(I64 x, I64 y, I64 z) : Vector(x, y, z) {}
-};
-
 // Position of a block within single chunk.
 class BlockLocal : public Vector<3, U8> {
 public:
-    BlockLocal(U8 x, U8 y, U8 z) : Vector(x, y, z) {}
-    BlockLocal(BlockOffset offset) : BlockLocal(offset.x(), offset.y(), offset.z()) {}
-    BlockOffset offset(BlockOffset by) {
+    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()),
@@ -42,8 +40,42 @@ public:
     }
 };
 
-const std::array<BlockOffset, 6> axis_directions = {{
+// 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), y(), 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::round(x); });
+        return {rounded.x(), rounded.y(), rounded.z()};
+    }
+};
+
 }