diff --git a/include/mcpp/util.h b/include/mcpp/util.h index 72c1fcf8..0ab1b891 100644 --- a/include/mcpp/util.h +++ b/include/mcpp/util.h @@ -100,6 +100,8 @@ struct Chunk { ~Chunk(); + Chunk& operator=(const Chunk& other) noexcept; + /** * Accesses the Minecraft block at absolute position pos and returns its * BlockType if it is in the included area. @@ -119,12 +121,36 @@ struct Chunk { */ BlockType get(int x, int y, int z); + /** + * Gets the x length of the Chunk. + * @return x length of the Chunk + */ + int x_len() const; + + /** + * Gets the y length of the Chunk. + * @return y length of the Chunk + */ + int y_len() const; + + /** + * Gets the z length of the Chunk. + * @return z length of the Chunk + */ + int z_len() const; + + /** + * Gets the minimum coordinate in the Chunk. + * @return the minimum coordinate in the Chunk + */ + Coordinate base_pt() const; + private: - Coordinate base_pt; + Coordinate _base_pt; + int _y_len; + int _x_len; + int _z_len; BlockType* raw_data; - int y_len; - int x_len; - int z_len; }; /** @@ -135,6 +161,10 @@ struct HeightMap { HeightMap(const Coordinate& loc1, const Coordinate& loc2, const std::vector& heights); + ~HeightMap(); + + HeightMap& operator=(const HeightMap& other) noexcept; + /** * Get the height using an offset from the origin/base point of the heights * area @@ -177,9 +207,9 @@ struct HeightMap { Coordinate base_pt() const; private: + Coordinate _base_pt; int _x_len; int _z_len; - Coordinate _base_pt; int* raw_heights; }; diff --git a/src/util.cpp b/src/util.cpp index 8d5ccd00..b4b80812 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -60,12 +60,12 @@ Chunk::Chunk(const Coordinate& loc1, const Coordinate& loc2, const std::vector& block_list) { Coordinate min{std::min(loc1.x, loc2.x), std::min(loc1.y, loc2.y), std::min(loc1.z, loc2.z)}; - this->base_pt = min.clone(); + this->_base_pt = min.clone(); Coordinate dim = loc1 - loc2; - x_len = std::abs(dim.x) + 1; - y_len = std::abs(dim.y) + 1; - z_len = std::abs(dim.z) + 1; + _x_len = std::abs(dim.x) + 1; + _y_len = std::abs(dim.y) + 1; + _z_len = std::abs(dim.z) + 1; this->raw_data = new BlockType[block_list.size()]; std::copy(block_list.begin(), block_list.end(), raw_data); @@ -73,27 +73,53 @@ Chunk::Chunk(const Coordinate& loc1, const Coordinate& loc2, Chunk::~Chunk() { delete[] raw_data; } +Chunk& Chunk::operator=(const Chunk& other) noexcept { + if (this != &other) { + // Clean up existing resource + delete[] raw_data; + + // Copy data from the other object + _base_pt = other._base_pt.clone(); + _x_len = other._x_len; + _y_len = other._y_len; + _z_len = other._z_len; + raw_data = new BlockType[_x_len * _y_len * _z_len]; + std::copy(other.raw_data, other.raw_data + _x_len * _y_len * _z_len, + raw_data); + } + return *this; +} + BlockType Chunk::get(int x, int y, int z) { if ((x < 0 || y < 0 || z < 0) || - (x > x_len - 1 || y > y_len - 1 || z > z_len - 1)) { + (x > _x_len - 1 || y > _y_len - 1 || z > _z_len - 1)) { 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[z + _z_len * (x + _y_len * y)]; } BlockType Chunk::get_worldspace(const Coordinate& pos) { - Coordinate array_pos = pos - base_pt; + Coordinate array_pos = pos - _base_pt; if ((array_pos.x < 0 || array_pos.y < 0 || array_pos.z < 0) || - (array_pos.x > x_len - 1 || array_pos.y > y_len - 1 || - array_pos.z > z_len - 1)) { + (array_pos.x > _x_len - 1 || array_pos.y > _y_len - 1 || + array_pos.z > _z_len - 1)) { throw std::out_of_range("Out of bounds Chunk access at " + 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.z + + _z_len * (array_pos.x + _y_len * array_pos.y)]; } +int Chunk::x_len() const { return this->_x_len; } + +int Chunk::y_len() const { return this->_y_len; } + +int Chunk::z_len() const { return this->_z_len; } + +Coordinate Chunk::base_pt() const { return this->_base_pt.clone(); } + HeightMap::HeightMap(const Coordinate& loc1, const Coordinate& loc2, const std::vector& heights) { _base_pt = Coordinate{ @@ -109,6 +135,26 @@ HeightMap::HeightMap(const Coordinate& loc1, const Coordinate& loc2, std::copy(heights.begin(), heights.end(), raw_heights); } +HeightMap::~HeightMap() { delete[] raw_heights; } + +HeightMap& HeightMap::operator=(const HeightMap& other) noexcept { + if (this != &other) { + // Free the existing resource + delete[] raw_heights; + + // Copy data from the other object + _base_pt = other._base_pt.clone(); + _x_len = other._x_len; + _z_len = other._z_len; + + // Allocate memory and copy the heights + raw_heights = new int[_x_len * _z_len]; + std::copy(other.raw_heights, other.raw_heights + _x_len * _z_len, + raw_heights); + } + return *this; +} + int HeightMap::get(int x, int z) const { if ((x < 0 || x >= _x_len) || (z < 0 || z >= _z_len)) { throw new std::out_of_range( diff --git a/test/minecraft_tests.cpp b/test/minecraft_tests.cpp index 00adb36a..011aee4d 100644 --- a/test/minecraft_tests.cpp +++ b/test/minecraft_tests.cpp @@ -140,6 +140,22 @@ TEST_CASE("getBlocks and Chunk operations") { mc.setBlock(loc1 + Coordinate{1, 2, 3}, Blocks::IRON_BLOCK); Chunk res = mc.getBlocks(loc1, loc2); + SUBCASE("getters") { + Chunk data = mc.getBlocks(loc1, loc2); + + CHECK_EQ(data.base_pt(), loc1); + CHECK_EQ(data.x_len(), 11); + CHECK_EQ(data.y_len(), 11); + CHECK_EQ(data.z_len(), 11); + + 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); + } + 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);