2** EPITECH PROJECT, 2025
12 ///////////////////////////////////////////////////////////////////////////
14 ///////////////////////////////////////////////////////////////////////////
16 template <Component T, typename Self>
17 auto Registry::subscribe(this Self &self)
18 -> std::expected<std::reference_wrapper<ConstLike<Self,
22 std::unique_lock lock(self._mutex);
23 std::type_index type = typeid(T);
25 if (self._arrays.contains(type)) [[unlikely]]
26 return std::unexpected{Error::failure(ErrorCode::InternalRuntimeError,
27 "Component already registered: {}",
30 auto [it, inserted] = self._arrays.emplace(
31 type, std::make_unique<SparseArray<T>>());
32 if (!inserted) [[unlikely]]
33 return std::unexpected{Error::failure(ErrorCode::InternalRuntimeError,
34 "Failed to register component: {}",
37 auto *rawPtr = static_cast<ConstLike<Self, SparseArray<T>> *>(it->second.get());
38 return std::ref(*rawPtr);
41 template <Component T, typename... Args>
42 auto Registry::add(Entity entity, Args &&...args)
43 -> std::expected<std::reference_wrapper<T>, rtp::Error>
45 std::unique_lock lock(this->_mutex);
46 std::type_index type = typeid(T);
48 if (!this->_arrays.contains(type)) [[unlikely]]
49 return std::unexpected{Error::failure(ErrorCode::ComponentMissing,
50 "Missing component: {}",
53 auto &ptr = this->_arrays.at(type);
54 auto *rawPtr = static_cast<SparseArray<T> *>(ptr.get());
56 return std::ref(rawPtr->emplace(entity, std::forward<Args>(args)...));
59 template <Component T, typename Self>
60 auto Registry::get(this const Self &self)
61 -> std::expected<std::reference_wrapper<ConstLike<Self,
65 std::shared_lock lock{self._mutex};
66 std::type_index type = typeid(T);
68 if (!self._arrays.contains(type)) [[unlikely]]
69 return std::unexpected{Error::failure(ErrorCode::ComponentMissing,
70 "Missing component: {}",
73 auto &ptr = self._arrays.find(type)->second;
74 auto *rawPtr = static_cast<SparseArray<T> *>(ptr.get());
76 return std::ref(*rawPtr);
79 template <Component T>
80 bool Registry::has(Entity entity) const noexcept
82 std::shared_lock lock{this->_mutex};
83 std::type_index type = typeid(T);
85 if (!this->_arrays.contains(type))
88 auto &ptr = this->_arrays.find(type)->second;
89 auto *rawPtr = static_cast<SparseArray<T> *>(ptr.get());
91 return rawPtr->has(entity);
94 template <Component T>
95 void Registry::remove(Entity entity) noexcept
97 std::type_index type = typeid(T);
100 std::shared_lock lock{this->_mutex};
102 if (!this->_arrays.contains(type)) [[unlikely]]
107 std::unique_lock lock{this->_mutex};
109 if (!this->_arrays.contains(type)) [[unlikely]]
111 auto &ptr = this->_arrays.find(type)->second;
112 auto *rawPtr = static_cast<SparseArray<T> *>(ptr.get());
114 rawPtr->erase(entity);
118 template <Component... Ts, typename Self>
119 auto Registry::view(this Self &self)
121 std::shared_lock lock{self._mutex};
123 if constexpr (sizeof...(Ts) == 1) {
124 using T = std::tuple_element_t<0, std::tuple<Ts...>>;
125 auto result = self.template get<T>();
126 if (!result.has_value()) {
127 return std::span<ConstLike<Self, T>>{};
129 return result->get().data();
131 auto &base = self.template getSmallestArray<Ts...>();
132 return std::views::iota(std::size_t{0}, base.size())
133 | std::views::transform([&](std::size_t i) {
134 Entity e = base.entities()[i];
135 return std::tuple<Entity, Ts&...>(
136 e, self.template getArray<Ts>()[e]...);
138 | std::views::filter([&](auto const &t) {
139 Entity e = std::get<0>(t);
140 return (self.template getArray<Ts>().has(e) && ...);
145 template <Component... Ts, typename Self>
146 auto Registry::zipView(this Self &self)
148 std::shared_lock lock{self._mutex};
150 auto get_array = [&]<typename T>() -> ConstLikeRef<Self, SparseArray<T>> {
151 std::type_index index(typeid(T));
153 if (self._arrays.find(index) == self._arrays.end()) {
154 throw rtp::Error::failure(ErrorCode::ComponentMissing,
155 "Component not registered in zipView: {}",
159 return static_cast<ConstLikeRef<Self, SparseArray<T>>>(*self._arrays.at(index));
162 return ZipView<ConstLikeRef<Self, SparseArray<Ts>>...>(
163 get_array.template operator()<Ts>()...);
166 ///////////////////////////////////////////////////////////////////////////
168 ///////////////////////////////////////////////////////////////////////////
170 template <Component T, typename Self>
171 auto Registry::getArray(this Self &self) -> ConstLikeRef<Self, SparseArray<T>>
173 std::shared_lock lock{self._mutex};
175 auto it = self._arrays.find(typeid(T));
176 if (it == self._arrays.end()) [[unlikely]]
177 throw rtp::Error::failure(ErrorCode::ComponentMissing,
178 "Component not registered: {}",
181 return static_cast<ConstLikeRef<Self, SparseArray<T>>>(*it->second);
184 template <Component T, Component... Ts, typename Self>
185 auto &Registry::getSmallestArray(this Self &self)
187 if constexpr (sizeof...(Ts) == 0) {
188 return self.template getArray<T>();
190 auto &firstArray = self.template getArray<T>();
191 auto &restSmallest = self.template getSmallestArray<Ts...>();
193 return (firstArray.size() < restSmallest.size()) ? firstArray
198 template <Component... Ts>
199 bool Registry::hasAllComponents(Entity entity) const noexcept
201 return (... && this->has<Ts>(entity));