Skip to content

Commit

Permalink
feat(ECS): Add SparseArrays class for ECS
Browse files Browse the repository at this point in the history
  • Loading branch information
MasterLaplace committed Jan 8, 2024
1 parent 1d13197 commit d0ec8ea
Show file tree
Hide file tree
Showing 2 changed files with 198 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set(HEADERS
Flakkari/Protocol/Header.hpp
Flakkari/Protocol/Packet.hpp
Flakkari/Engine/EntityComponentSystem/Entity.hpp
Flakkari/Engine/EntityComponentSystem/SparseArrays.hpp
Flakkari/Server/UDPServer.hpp
Flakkari/Server/Client/Client.hpp
Flakkari/Server/Client/ClientManager.hpp
Expand Down
197 changes: 197 additions & 0 deletions Flakkari/Engine/EntityComponentSystem/SparseArrays.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/**************************************************************************
* Flakkari Library v0.1.0
*
* Flakkari Library is a C++ Library for Network.
* @file SparseArrays.hpp
* @brief SparseArrays class for ECS (Entity Component System).
*
* Flakkari Library is under MIT License.
* https://opensource.org/licenses/MIT
* © 2023 @MasterLaplace
* @version 0.1.0
* @date 2023-01-05
**************************************************************************/


#ifndef SPARSEARRAYS_HPP_
#define SPARSEARRAYS_HPP_

#include <vector>
#include <optional>
#include <type_traits>
#include <algorithm>

namespace Flakkari::Engine::ECS {

template <typename Component>
class SparseArrays {
public:
using value_type = std::optional<Component>;
using reference_type = value_type&;
using const_reference_type = const value_type&;
using container_type = std::vector<value_type>;
using size_type = typename container_type::size_type;
using iterator = typename container_type::iterator;
using const_iterator = typename container_type::const_iterator;

public:
SparseArrays() = default;
SparseArrays(const SparseArrays &other) : _data(other._data) {};
SparseArrays(SparseArrays&&other) noexcept : _data(std::move(other._data)) {};
~SparseArrays() = default;

/**
* @brief Copy assignment operator for SparseArrays.
*
* @param other The SparseArrays to copy.
* @return SparseArrays& The SparseArrays copied.
*/
SparseArrays &operator=(SparseArrays const &other) {
_data = std::move(other._data);
return *this;
}

/**
* @brief Move assignment operator for SparseArrays.
*
* @param other The SparseArrays to move.
* @return SparseArrays& The SparseArrays moved.
*/
SparseArrays &operator=(SparseArrays &&other) noexcept
{
if (this != &other)
std::swap(_data, other._data);

return *this;
}

/**
* @brief Get the component at the index.
*
* @param idx The index of the component.
* @return reference_type The component.
*/
reference_type operator[](size_type idx)
{
if (idx >= _data.size())
_data.resize(idx + 1, std::nullopt);

return _data[idx];
}

/**
* @brief Get the component at the index.
* Const version.
*
* @param idx The index of the component.
* @return const_reference_type The component.
*/
const_reference_type operator[](size_type idx) const
{
if (idx >= _data.size())
return std::nullopt;

return _data[idx];
}

iterator begin() { return _data.begin(); }

const_iterator begin() const { return _data.begin(); }

const_iterator cbegin() const { return _data.cbegin(); }

iterator end() { return _data.end(); }

const_iterator end() const { return _data.end(); }

const_iterator cend() const { return _data.cend(); }

size_type size() const { return _data.size(); }

/**
* @brief Insert a component at the end of the SparseArrays.
*
* @param pos The position of the component.
* @param component The component to insert.
* @return reference_type The component inserted.
*/
reference_type insert_at(size_type pos, const Component &component)
{
if (pos >= _data.size())
_data.resize(pos + 1, std::nullopt);

_data[pos].emplace(component);
return _data[pos];
}

/**
* @brief Insert a component at the end of the SparseArrays.
* Move version.
*
* @param pos The position of the component.
* @param component The component to insert.
* @return reference_type The component inserted.
*/
reference_type insert_at(size_type pos, Component &&component)
{
if (pos >= _data.size())
_data.resize(pos + 1, std::nullopt);

_data[pos] = std::move(component);
return _data[pos];
}

/**
* @brief Emplace a component at the end of the SparseArrays.
*
* @tparam Params The parameters to construct the component.
* @param pos The position of the component.
* @param params The parameters to construct the component.
* @return reference_type The component inserted.
*/
template <class... Params>
reference_type emplace_at(size_type pos, Params&&... params)
{
if (pos >= _data.size())
_data.resize(pos + 1, std::nullopt);

_data[pos].emplace(std::forward<Params>(params)...);
return _data[pos];
}

/**
* @brief Erase a component at the position.
*
* @param pos The position of the component to erase.
*/
void erase(size_type pos)
{
if (pos < _data.size())
_data[pos].reset();
}

/**
* @brief Get the index object from a component.
*
* @param component The component to get the index from.
* @return size_type The index of the component.
*/
size_type get_index(value_type const &component) const
{
auto it = std::find_if(_data.begin(), _data.end(), [&component](auto const& opt) {
return opt.has_value() && opt.value() == component;
});

if (it == _data.end())
return _data.size();

return std::distance(_data.begin(), it);
}

private:
container_type _data;
};

} // namespace Flakkari::Engine::ECS

#endif /* !SPARSEARRAYS_HPP_ */

0 comments on commit d0ec8ea

Please sign in to comment.