From 9db201663da00ebdeceb8bfc38003b6795e1fabb Mon Sep 17 00:00:00 2001 From: nhatdongdang <144138246+nhatdongdang@users.noreply.github.com> Date: Mon, 12 Aug 2024 18:11:29 +1000 Subject: [PATCH 1/3] Add chunk iterator and documentation --- include/mcpp/util.h | 91 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/include/mcpp/util.h b/include/mcpp/util.h index 53c87a77..8a0b0cb3 100644 --- a/include/mcpp/util.h +++ b/include/mcpp/util.h @@ -92,6 +92,97 @@ struct Coordinate { * the base point they were gathered at and each other. */ struct Chunk { + /** + * @brief An iterator for the Chunk's 3D block data. + * + * This iterator allows for range-based for loops and standard iterator + * operations over the 3D block data stored within a Chunk. It provides a + * linear interface to traverse the 3D grid of blocks, enabling sequential + * access to the elements stored in the chunk. + */ + struct Iterator { + using value_type = BlockType; + using pointer = BlockType*; + using reference = BlockType&; + + /** + * @brief Constructs an iterator at the given pointer position. + * + * @param ptr Pointer to the position in the height array. + */ + Iterator(pointer ptr) : m_ptr(ptr) {} + + /** + * @brief Dereference the iterator to access the value at the current + * position. + * + * @return Reference to the current element. + */ + reference operator*() const { return *m_ptr; } + + /** + * @brief Access the pointer to the current element. + * + * @return Pointer to the current element. + */ + pointer operator->() { return m_ptr; } + + /** + * @brief Pre-increment operator. Advances the iterator to the next + * position. + * + * @return Reference to the updated iterator. + */ + Iterator& operator++() { + m_ptr++; + return *this; + } + + /** + * @brief Post-increment operator. Advances the iterator to the next + * position. + * + * @param int Unused dummy parameter to differentiate from prefix + * increment. + * @return Iterator to the original position before incrementing. + */ + Iterator operator++(int) { + Iterator tmp = *this; + ++(*this); + return tmp; + } + + /** + * @brief Equality comparison operator. + * + * @param a First iterator to compare. + * @param b Second iterator to compare. + * @return true if both iterators point to the same position, false + * otherwise. + */ + friend bool operator==(const Iterator& a, const Iterator& b) { + return a.m_ptr == b.m_ptr; + }; + + /** + * @brief Inequality comparison operator. + * + * @param a First iterator to compare. + * @param b Second iterator to compare. + * @return true if iterators point to different positions, false + * otherwise. + */ + friend bool operator!=(const Iterator& a, const Iterator& b) { + return a.m_ptr != b.m_ptr; + }; + + private: + pointer m_ptr; + }; + + Iterator begin() { return Iterator(&raw_data[0]); } + Iterator end() { return Iterator(&raw_data[_x_len * _z_len * _z_len]); } + /** * Initialized by copying from a flat vector of blocks */ From 978a4fea114e8e58e748a14ca6b7196b1929435b Mon Sep 17 00:00:00 2001 From: nhatdongdang <144138246+nhatdongdang@users.noreply.github.com> Date: Mon, 12 Aug 2024 18:11:57 +1000 Subject: [PATCH 2/3] Add iterator testcase and fix chunk getter --- src/util.cpp | 6 +++--- test/minecraft_tests.cpp | 36 +++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index b4b80812..03d08f03 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -96,7 +96,7 @@ BlockType Chunk::get(int x, int y, int z) { throw std::out_of_range("Out of bounds Chunk access at " + to_string(Coordinate(x, y, z))); } - return raw_data[z + _z_len * (x + _y_len * y)]; + return raw_data[y * _x_len * _z_len + x * _z_len + z]; } BlockType Chunk::get_worldspace(const Coordinate& pos) { @@ -108,8 +108,8 @@ BlockType Chunk::get_worldspace(const Coordinate& pos) { to_string(array_pos) + " (world coordinate " + to_string(pos) + " )"); } - return raw_data[array_pos.z + - _z_len * (array_pos.x + _y_len * array_pos.y)]; + return raw_data[array_pos.y * _x_len * _z_len + array_pos.x * _z_len + + array_pos.z]; } int Chunk::x_len() const { return this->_x_len; } diff --git a/test/minecraft_tests.cpp b/test/minecraft_tests.cpp index 322b66aa..7f4b707f 100644 --- a/test/minecraft_tests.cpp +++ b/test/minecraft_tests.cpp @@ -127,10 +127,11 @@ TEST_CASE("Test the main mcpp class") { } TEST_CASE("getBlocks and Chunk operations") { + // Setup Coordinate test_loc(100, 100, 100); Coordinate loc1{100, 100, 100}; - Coordinate loc2{110, 110, 110}; + Coordinate loc2{110, 111, 112}; // Reset blocks that existed before mc.setBlocks(loc1, loc2, Blocks::AIR); @@ -145,22 +146,22 @@ TEST_CASE("getBlocks and Chunk operations") { CHECK_EQ(data.base_pt(), loc1); CHECK_EQ(data.x_len(), 11); - CHECK_EQ(data.y_len(), 11); - CHECK_EQ(data.z_len(), 11); + CHECK_EQ(data.y_len(), 12); + CHECK_EQ(data.z_len(), 13); data = mc.getBlocks(loc2, loc1); CHECK_EQ(data.base_pt(), loc1); CHECK_EQ(data.x_len(), 11); - CHECK_EQ(data.y_len(), 11); - CHECK_EQ(data.z_len(), 11); + CHECK_EQ(data.y_len(), 12); + CHECK_EQ(data.z_len(), 13); } SUBCASE("Block accessing returns correct block using get()") { CHECK_EQ(res.get(0, 0, 0), Blocks::GOLD_BLOCK); CHECK_EQ(res.get(1, 1, 1), Blocks::BRICKS); CHECK_EQ(res.get(1, 2, 3), Blocks::IRON_BLOCK); - CHECK_EQ(res.get(10, 10, 10), Blocks::DIAMOND_BLOCK); + CHECK_EQ(res.get(10, 11, 12), Blocks::DIAMOND_BLOCK); } SUBCASE("Block accessing returns correct block using get_worldspace()") { @@ -174,13 +175,30 @@ TEST_CASE("getBlocks and Chunk operations") { SUBCASE("Access out of bounds correctly throws") { CHECK_THROWS(res.get(11, 0, 0)); - CHECK_THROWS(res.get(0, 11, 0)); - CHECK_THROWS(res.get(0, 0, 11)); + CHECK_THROWS(res.get(0, 12, 0)); + CHECK_THROWS(res.get(0, 0, 13)); CHECK_THROWS(res.get(-1, 0, 0)); CHECK_THROWS(res.get(0, -1, 0)); CHECK_THROWS(res.get(0, 0, -1)); CHECK_THROWS(res.get_worldspace(loc1 + Coordinate{-1, -1, -1})); - CHECK_THROWS(res.get_worldspace(loc1 + Coordinate{11, 11, 11})); + CHECK_THROWS(res.get_worldspace(loc1 + Coordinate{11, 12, 13})); + } + + SUBCASE("Iterator") { + std::vector blocks; + for (int i = 0; i < res.y_len(); i++) { + for (int j = 0; j < res.x_len(); j++) { + for (int z = 0; z < res.z_len(); z++) { + blocks.push_back(res.get(j, i, z)); + } + } + } + + std::vector expected_blocks; + for (BlockType block : res) { + expected_blocks.push_back(block); + } + CHECK_NE(blocks, expected_blocks); } mc.setBlock(test_loc, BlockType(0)); From 2d99dd6da1bcf06429e22d29a769962e6aee5ff4 Mon Sep 17 00:00:00 2001 From: nhatdongdang <144138246+nhatdongdang@users.noreply.github.com> Date: Mon, 12 Aug 2024 18:27:38 +1000 Subject: [PATCH 3/3] Fix iterator bug --- include/mcpp/util.h | 2 +- test/minecraft_tests.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mcpp/util.h b/include/mcpp/util.h index 8a0b0cb3..640eb716 100644 --- a/include/mcpp/util.h +++ b/include/mcpp/util.h @@ -181,7 +181,7 @@ struct Chunk { }; Iterator begin() { return Iterator(&raw_data[0]); } - Iterator end() { return Iterator(&raw_data[_x_len * _z_len * _z_len]); } + Iterator end() { return Iterator(&raw_data[_x_len * _y_len * _z_len]); } /** * Initialized by copying from a flat vector of blocks diff --git a/test/minecraft_tests.cpp b/test/minecraft_tests.cpp index 7f4b707f..7032c9f7 100644 --- a/test/minecraft_tests.cpp +++ b/test/minecraft_tests.cpp @@ -198,7 +198,7 @@ TEST_CASE("getBlocks and Chunk operations") { for (BlockType block : res) { expected_blocks.push_back(block); } - CHECK_NE(blocks, expected_blocks); + CHECK_EQ(blocks, expected_blocks); } mc.setBlock(test_loc, BlockType(0));