CommonLibVR
RegistrationMapUnique.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "RE/A/ActiveEffect.h"
4 #include "RE/B/BGSRefAlias.h"
5 #include "RE/B/BSFixedString.h"
8 #include "RE/T/TESForm.h"
9 #include "RE/T/TESObjectREFR.h"
10 #include "RE/T/TypeTraits.h"
11 #include "RE/V/VirtualMachine.h"
12 
13 #include "SKSE/API.h"
15 #include "SKSE/Interfaces.h"
16 #include "SKSE/Logger.h"
17 
18 namespace SKSE
19 {
20  namespace Impl
21  {
22  template <class Filter>
24  {
25  public:
26  using EventFilter = std::pair<Filter, bool>;
27  using EventFilterHandleMap = std::map<EventFilter, std::set<RE::VMHandle>>;
28 
29  using PassFilterFunc = std::function<bool(const Filter&, bool)>;
30 
32  {
33  public:
35  RegistrationMapUniqueBase(const std::string_view& a_eventName);
39 
42 
43  bool Register(RE::TESForm* a_form, const Filter& a_filter, bool a_matchFilter);
44  bool Register(RE::ActiveEffect* a_activeEffect, const Filter& a_filter, bool a_matchFilter);
45  bool Register(RE::BGSRefAlias* a_alias, const Filter& a_filter, bool a_matchFilter);
46  bool Unregister(RE::TESForm* a_form, const Filter& a_filter, bool a_matchFilter);
47  bool Unregister(RE::ActiveEffect* a_activeEffect, const Filter& a_filter, bool a_matchFilter);
48  bool Unregister(RE::BGSRefAlias* a_alias, const Filter& a_filter, bool a_matchFilter);
49  void UnregisterAll(const RE::TESForm* a_form);
50  void UnregisterAll(RE::ActiveEffect* a_activeEffect);
51  void UnregisterAll(RE::BGSRefAlias* a_alias);
52  void UnregisterAll(RE::VMHandle a_handle);
53  void UnregisterAll(RE::FormID a_uniqueID);
54  void Clear();
55  bool Save(SerializationInterface* a_intfc, std::uint32_t a_type, std::uint32_t a_version);
56  bool Save(SerializationInterface* a_intfc);
57  bool Load(SerializationInterface* a_intfc);
59 
60  protected:
61  using Lock = std::recursive_mutex;
62  using Locker = std::lock_guard<Lock>;
63 
64  bool Register(const void* a_object, RE::FormID a_formID, EventFilter a_filter, RE::VMTypeID a_typeID);
65  bool Unregister(const void* a_object, RE::FormID a_formID, EventFilter a_filter, RE::VMTypeID a_typeID);
66  void UnregisterAll(const void* a_object, RE::FormID a_formID, RE::VMTypeID a_typeID);
67 
68  std::map<RE::FormID, EventFilterHandleMap> _regs;
70  mutable Lock _lock;
71  };
72 
73  template <class Enable, class... Args>
75 
76  template <class... Args>
78  std::enable_if_t<
79  std::conjunction_v<
80  RE::BSScript::is_return_convertible<Args>...>>,
81  Args...> :
83  {
84  private:
86 
87  public:
91 
92  inline RegistrationMapUnique(const std::string_view& a_eventName) :
93  super(a_eventName)
94  {}
95 
97 
100 
101  inline void SendEvent(const RE::TESObjectREFR* a_target, PassFilterFunc a_callback, Args... a_args)
102  {
103  RE::BSFixedString eventName(this->_eventName);
104 
106  const auto targetFormID = a_target->GetFormID();
107  if (auto it = this->_regs.find(targetFormID); it != this->_regs.end()) {
108  for (auto& [eventFilter, handles] : it->second) {
109  if (a_callback(eventFilter.first, eventFilter.second)) {
110  for (auto& handle : handles) {
111  auto args = RE::MakeFunctionArguments(std::forward<Args>(a_args)...);
112  vm->SendEvent(handle, eventName, args);
113  }
114  }
115  }
116  }
117  }
118  }
119 
120  inline void QueueEvent(RE::TESObjectREFR* a_target, PassFilterFunc a_callback, Args... a_args)
121  {
122  std::tuple args(VMArg(std::forward<Args>(a_args))...);
123  auto task = GetTaskInterface();
124  assert(task);
125  if (task) {
126  task->AddTask([a_target, a_callback, args, this]() mutable {
127  SendEvent_Tuple(a_target, a_callback, std::move(args), index_sequence_for_tuple<decltype(args)>{});
128  });
129  }
130  }
131 
132  private:
133  template <class Tuple, std::size_t... I>
134  inline void SendEvent_Tuple(RE::TESObjectREFR* a_target, PassFilterFunc a_callback, Tuple&& a_tuple, std::index_sequence<I...>)
135  {
136  SendEvent(a_target, a_callback, std::get<I>(std::forward<Tuple>(a_tuple)).Unpack()...);
137  }
138  };
139 
140  template <>
142  {
143  private:
145 
146  public:
150 
151  inline RegistrationMapUnique(const std::string_view& a_eventName) :
152  super(a_eventName)
153  {}
154 
156 
159 
160  inline void SendEvent(const RE::TESObjectREFR* a_target, PassFilterFunc a_callback)
161  {
162  RE::BSFixedString eventName(this->_eventName);
163 
165  const auto targetFormID = a_target->GetFormID();
166  if (auto it = this->_regs.find(targetFormID); it != this->_regs.end()) {
167  for (auto& [eventFilter, handles] : it->second) {
168  if (a_callback(eventFilter.first, eventFilter.second)) {
169  for (auto& handle : handles) {
170  auto args = RE::MakeFunctionArguments();
171  vm->SendEvent(handle, eventName, args);
172  }
173  }
174  }
175  }
176  }
177  }
178 
179  inline void QueueEvent(RE::TESObjectREFR* a_target, PassFilterFunc a_callback)
180  {
181  auto task = GetTaskInterface();
182  assert(task);
183  task->AddTask([a_target, a_callback, this]() {
184  SendEvent(a_target, std::move(a_callback));
185  });
186  }
187  };
188  };
189 
190  template <class Filter>
192  _regs(),
193  _eventName(a_eventName),
194  _lock()
195  {}
196 
197  template <class Filter>
199  _regs(),
200  _eventName(a_rhs._eventName),
201  _lock()
202  {
203  a_rhs._lock.lock();
204  _regs = a_rhs._regs;
205  a_rhs._lock.unlock();
206 
208  if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
209  for (auto& reg : _regs) {
210  for (auto& keyHandles : reg.second) {
211  for (auto& handle : keyHandles.second) {
212  policy->PersistHandle(handle);
213  }
214  }
215  }
216  }
217  }
218 
219  template <class Filter>
221  _regs(),
222  _eventName(a_rhs._eventName),
223  _lock()
224  {
225  Locker locker(a_rhs._lock);
226  _regs = std::move(a_rhs._regs);
227  a_rhs._regs.clear();
228  }
229 
230  template <class Filter>
232  {
234  if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
235  for (auto& reg : _regs) {
236  for (auto& keyHandles : reg.second) {
237  for (auto& handle : keyHandles.second) {
238  policy->ReleaseHandle(handle);
239  }
240  }
241  }
242  }
243  }
244 
245  template <class Filter>
247  {
248  if (this == &a_rhs) {
249  return *this;
250  }
251 
252  Locker lhsLocker(_lock);
253  Clear();
254 
255  {
256  Locker rhsLocker(a_rhs._lock);
257  _regs = a_rhs._regs;
258  _eventName = a_rhs._eventName;
259  }
260 
262  if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
263  for (auto& reg : _regs) {
264  for (auto& keyHandles : reg.second) {
265  for (auto& handle : keyHandles.second) {
266  policy->PersistHandle(handle);
267  }
268  }
269  }
270  }
271 
272  return *this;
273  }
274 
275  template <class Filter>
277  {
278  if (this == &a_rhs) {
279  return *this;
280  }
281 
282  Locker lhsLocker(_lock);
283  Locker rhsLocker(a_rhs._lock);
284 
285  Clear();
286 
287  _eventName = a_rhs._eventName;
288 
289  _regs = std::move(a_rhs._regs);
290  a_rhs._regs.clear();
291 
292  return *this;
293  }
294 
295  template <class Filter>
296  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Register(RE::TESForm* a_form, const Filter& a_filter, bool a_matchFilter)
297  {
298  assert(a_form);
299 
300  const auto reference = a_form->AsReference();
301  const auto formID = reference ? reference->GetFormID() : 0;
302 
303  if (formID != 0) {
304  return Register(a_form, formID, { a_filter, a_matchFilter }, static_cast<RE::VMTypeID>(a_form->GetFormType()));
305  }
306 
307  return false;
308  }
309 
310  template <class Filter>
311  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Register(RE::ActiveEffect* a_activeEffect, const Filter& a_filter, bool a_matchFilter)
312  {
313  assert(a_activeEffect);
314 
315  const auto target = a_activeEffect->GetTargetActor();
316  const auto formID = target ? target->GetFormID() : 0;
317 
318  if (formID != 0) {
319  return Register(a_activeEffect, formID, { a_filter, a_matchFilter }, RE::ActiveEffect::VMTYPEID);
320  }
321 
322  return false;
323  }
324 
325  template <class Filter>
326  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Register(RE::BGSRefAlias* a_alias, const Filter& a_filter, bool a_matchFilter)
327  {
328  assert(a_alias);
329 
330  const auto target = a_alias->GetActorReference();
331  const auto formID = target ? target->GetFormID() : 0;
332 
333  if (formID != 0) {
334  return Register(a_alias, formID, { a_filter, a_matchFilter }, RE::BGSRefAlias::VMTYPEID);
335  }
336 
337  return false;
338  }
339 
340  template <class Filter>
341  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Unregister(RE::TESForm* a_form, const Filter& a_filter, bool a_matchFilter)
342  {
343  assert(a_form);
344 
345  const auto reference = a_form->AsReference();
346  const auto formID = reference ? reference->GetFormID() : 0;
347 
348  if (formID != 0) {
349  return Unregister(a_form, formID, { a_filter, a_matchFilter }, static_cast<RE::VMTypeID>(a_form->GetFormType()));
350  }
351 
352  return false;
353  }
354 
355  template <class Filter>
356  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Unregister(RE::ActiveEffect* a_activeEffect, const Filter& a_filter, bool a_matchFilter)
357  {
358  assert(a_activeEffect);
359 
360  const auto target = a_activeEffect->GetTargetActor();
361  const auto formID = target ? target->GetFormID() : 0;
362 
363  if (formID != 0) {
364  return Unregister(a_activeEffect, formID, { a_filter, a_matchFilter }, RE::ActiveEffect::VMTYPEID);
365  }
366 
367  return false;
368  }
369 
370  template <class Filter>
371  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Unregister(RE::BGSRefAlias* a_alias, const Filter& a_filter, bool a_matchFilter)
372  {
373  assert(a_alias);
374 
375  const auto target = a_alias->GetActorReference();
376  const auto formID = target ? target->GetFormID() : 0;
377 
378  if (formID != 0) {
379  return Unregister(a_alias, formID, { a_filter, a_matchFilter }, RE::BGSRefAlias::VMTYPEID);
380  }
381 
382  return false;
383  }
384 
385  template <class Filter>
387  {
388  assert(a_form);
389 
390  const auto reference = a_form->AsReference();
391  const auto formID = reference ? reference->GetFormID() : 0;
392 
393  if (formID != 0) {
394  UnregisterAll(a_form, formID, static_cast<RE::VMTypeID>(a_form->GetFormType()));
395  }
396  }
397 
398  template <class Filter>
400  {
401  assert(a_activeEffect);
402 
403  const auto target = a_activeEffect->GetTargetActor();
404  const auto formID = target ? target->GetFormID() : 0;
405 
406  if (formID != 0) {
407  UnregisterAll(a_activeEffect, formID, RE::ActiveEffect::VMTYPEID);
408  }
409  }
410 
411  template <class Filter>
413  {
414  assert(a_alias);
415 
416  const auto target = a_alias->GetActorReference();
417  const auto formID = target ? target->GetFormID() : 0;
418 
419  if (formID != 0) {
420  UnregisterAll(a_alias, formID, RE::BGSRefAlias::VMTYPEID);
421  }
422  }
423 
424  template <class Filter>
426  {
428  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
429  if (!policy) {
430  log::error("Failed to get handle policy!");
431  return;
432  }
433 
434  Locker locker(_lock);
435  for (auto& reg : _regs) {
436  for (auto& keyHandle : reg.second) {
437  if (auto result = keyHandle.second.erase(a_handle); result != 0) {
438  policy->ReleaseHandle(a_handle);
439  }
440  }
441  }
442  }
443 
444  template <class Filter>
446  {
448  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
449  if (!policy) {
450  log::error("Failed to get handle policy!");
451  return;
452  }
453 
454  Locker locker(_lock);
455  auto it = _regs.find(a_uniqueID);
456  if (it != _regs.end()) {
457  for (auto& keyHandles : it->second) {
458  for (auto& handle : keyHandles.second) {
459  policy->ReleaseHandle(handle);
460  }
461  }
462  _regs.erase(it);
463  }
464  }
465 
466  template <class Filter>
468  {
470  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
471  Locker locker(_lock);
472  if (policy) {
473  for (auto& reg : _regs) {
474  for (auto& keyHandle : reg.second) {
475  for (auto& handle : keyHandle.second) {
476  policy->ReleaseHandle(handle);
477  }
478  }
479  }
480  }
481  _regs.clear();
482  }
483 
484  template <class Filter>
485  bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Save(SerializationInterface* a_intfc, std::uint32_t a_type, std::uint32_t a_version)
486  {
487  assert(a_intfc);
488  if (!a_intfc->OpenRecord(a_type, a_version)) {
489  log::error("Failed to open record!");
490  return false;
491  }
492 
493  return Save(a_intfc);
494  }
495 
496  template <class Filter>
498  {
499  assert(a_intfc);
500  Locker locker(_lock);
501 
502  // Reg count
503  const std::size_t numRegs = _regs.size();
504  if (!a_intfc->WriteRecordData(numRegs)) {
505  log::error("Failed to save reg count ({})!", numRegs);
506  return false;
507  }
508  for (auto& reg : _regs) {
509  //FormID
510  if (!a_intfc->WriteRecordData(reg.first)) {
511  log::error("Failed to save handle formID ({:X})", reg.first);
512  return false;
513  }
514  std::size_t numUniqueHandle = reg.second.size();
515  if (!a_intfc->WriteRecordData(numUniqueHandle)) {
516  log::error("Failed to save handle count ({})!", numUniqueHandle);
517  return false;
518  }
519  // UniqueHandle
520  for (auto& [key, handles] : reg.second) {
521  // EventFilter
522  auto [eventFilter, match] = key;
523  if (!eventFilter.Save(a_intfc)) {
524  log::error("Failed to save event filters!");
525  return false;
526  }
527  if (!a_intfc->WriteRecordData(match)) {
528  log::error("Failed to save reg key as bool ({})!", match);
529  return false;
530  }
531  //handle set
532  std::size_t numHandles = handles.size();
533  if (!a_intfc->WriteRecordData(numHandles)) {
534  log::error("Failed to save handle count ({})!", numHandles);
535  return false;
536  }
537  for (auto& handle : handles) {
538  if (!a_intfc->WriteRecordData(handle)) {
539  log::error("Failed to save handle ({})", handle);
540  return false;
541  }
542  }
543  }
544  }
545 
546  return true;
547  }
548 
549  template <class Filter>
551  {
552  assert(a_intfc);
553  std::size_t numRegs;
554  a_intfc->ReadRecordData(numRegs);
555 
556  Locker locker(_lock);
557  _regs.clear();
558 
559  //FormID
560  RE::FormID formID;
561  // KeyHandle
562  std::size_t numKeyHandle;
563  // Handle
564  std::size_t numHandles;
565  RE::VMHandle vmHandle;
566 
567  for (std::size_t i = 0; i < numRegs; ++i) {
568  a_intfc->ReadRecordData(formID);
569  if (!a_intfc->ResolveFormID(formID, formID)) {
570  log::warn("Failed to resolve target formID ({:X})", formID);
571  continue;
572  }
573  a_intfc->ReadRecordData(numKeyHandle);
574  for (std::size_t j = 0; j < numKeyHandle; ++j) {
575  // filter
576  Filter eventFilter{};
577  if (!eventFilter.Load(a_intfc)) {
578  log::error("Failed to save event filters!");
579  continue;
580  }
581  bool match;
582  a_intfc->ReadRecordData(match);
583  EventFilter curKey = { eventFilter, match };
584  // handles
585  a_intfc->ReadRecordData(numHandles);
586  for (std::size_t k = 0; k < numHandles; ++k) {
587  a_intfc->ReadRecordData(vmHandle);
588  if (a_intfc->ResolveHandle(vmHandle, vmHandle)) {
589  _regs[formID][curKey].insert(vmHandle);
590  }
591  }
592  }
593  }
594 
595  return true;
596  }
597 
598  template <class Filter>
600  {
601  Clear();
602  }
603 
604  template <class Filter>
606  {
607  assert(a_object);
609  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
610  if (!policy) {
611  log::error("Failed to get handle policy!");
612  return false;
613  }
614 
615  const auto invalidHandle = policy->EmptyHandle();
616  auto handle = policy->GetHandleForObject(a_typeID, a_object);
617  if (handle == invalidHandle) {
618  log::error("Failed to create handle!");
619  return false;
620  }
621 
622  _lock.lock();
623  auto result = _regs[a_formID][a_filter].insert(handle);
624  _lock.unlock();
625 
626  if (result.second) {
627  policy->PersistHandle(handle);
628  }
629 
630  return result.second;
631  }
632 
633  template <class Filter>
635  {
636  assert(a_object);
638  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
639  if (!policy) {
640  log::error("Failed to get handle policy!");
641  return false;
642  }
643 
644  const auto invalidHandle = policy->EmptyHandle();
645  const auto handle = policy->GetHandleForObject(a_typeID, a_object);
646  if (handle == invalidHandle) {
647  log::error("Failed to create handle!");
648  return false;
649  }
650 
651  Locker locker(_lock);
652  if (auto formIt = _regs.find(a_formID); formIt != _regs.end()) {
653  if (auto keyIt = formIt->second.find(a_filter); keyIt != formIt->second.end()) {
654  if (auto result = keyIt->second.erase(handle); result != 0) {
655  policy->ReleaseHandle(handle);
656  return true;
657  }
658  }
659  }
660 
661  return false;
662  }
663 
664  template <class Filter>
666  {
667  assert(a_object);
669  auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
670  if (!policy) {
671  log::error("Failed to get handle policy!");
672  return;
673  }
674 
675  const auto invalidHandle = policy->EmptyHandle();
676  const auto handle = policy->GetHandleForObject(a_typeID, a_object);
677  if (handle == invalidHandle) {
678  log::error("Failed to create handle!");
679  return;
680  }
681 
682  Locker locker(_lock);
683  if (auto it = _regs.find(a_formID); it != _regs.end()) {
684  for (auto& keyHandles : it->second) {
685  if (auto result = keyHandles.second.erase(handle); result != 0) {
686  policy->ReleaseHandle(handle);
687  }
688  }
689  }
690  }
691  }
692 
693  template <class Filter, class... Args>
695 }
Definition: ActiveEffect.h:27
static constexpr auto VMTYPEID
Definition: ActiveEffect.h:31
Actor * GetTargetActor()
Definition: BGSRefAlias.h:15
static constexpr auto VMTYPEID
Definition: BGSRefAlias.h:19
Actor * GetActorReference() const
static VirtualMachine * GetSingleton()
Definition: TESForm.h:40
TESObjectREFR * AsReference()
Definition: TESForm.h:275
FormType GetFormType() const noexcept
Definition: TESForm.h:294
FormID GetFormID() const noexcept
Definition: TESForm.h:293
Definition: TESObjectREFR.h:113
Definition: RegistrationMapUnique.h:32
std::recursive_mutex Lock
Definition: RegistrationMapUnique.h:61
bool Load(SerializationInterface *a_intfc)
Definition: RegistrationMapUnique.h:550
void Clear()
Definition: RegistrationMapUnique.h:467
~RegistrationMapUniqueBase()
Definition: RegistrationMapUnique.h:231
void Revert(SerializationInterface *)
Definition: RegistrationMapUnique.h:599
Lock _lock
Definition: RegistrationMapUnique.h:70
std::map< RE::FormID, EventFilterHandleMap > _regs
Definition: RegistrationMapUnique.h:68
bool Register(RE::TESForm *a_form, const Filter &a_filter, bool a_matchFilter)
Definition: RegistrationMapUnique.h:296
bool Save(SerializationInterface *a_intfc, std::uint32_t a_type, std::uint32_t a_version)
Definition: RegistrationMapUnique.h:485
RegistrationMapUniqueBase & operator=(const RegistrationMapUniqueBase &a_rhs)
Definition: RegistrationMapUnique.h:246
bool Unregister(RE::TESForm *a_form, const Filter &a_filter, bool a_matchFilter)
Definition: RegistrationMapUnique.h:341
void UnregisterAll(const RE::TESForm *a_form)
Definition: RegistrationMapUnique.h:386
std::string _eventName
Definition: RegistrationMapUnique.h:69
std::lock_guard< Lock > Locker
Definition: RegistrationMapUnique.h:62
void SendEvent(const RE::TESObjectREFR *a_target, PassFilterFunc a_callback, Args... a_args)
Definition: RegistrationMapUnique.h:101
void QueueEvent(RE::TESObjectREFR *a_target, PassFilterFunc a_callback, Args... a_args)
Definition: RegistrationMapUnique.h:120
RegistrationMapUnique & operator=(const RegistrationMapUnique &)=default
RegistrationMapUnique & operator=(RegistrationMapUnique &&)=default
RegistrationMapUnique(const RegistrationMapUnique &)=default
void SendEvent(const RE::TESObjectREFR *a_target, PassFilterFunc a_callback)
Definition: RegistrationMapUnique.h:160
RegistrationMapUnique(const std::string_view &a_eventName)
Definition: RegistrationMapUnique.h:151
void QueueEvent(RE::TESObjectREFR *a_target, PassFilterFunc a_callback)
Definition: RegistrationMapUnique.h:179
Definition: RegistrationMapUnique.h:74
Definition: RegistrationMapUnique.h:24
std::function< bool(const Filter &, bool)> PassFilterFunc
Definition: RegistrationMapUnique.h:29
std::map< EventFilter, std::set< RE::VMHandle > > EventFilterHandleMap
Definition: RegistrationMapUnique.h:27
std::pair< Filter, bool > EventFilter
Definition: RegistrationMapUnique.h:26
Definition: Interfaces.h:82
bool ResolveHandle(RE::VMHandle a_oldHandle, RE::VMHandle &a_newHandle) const
std::uint32_t ReadRecordData(void *a_buf, std::uint32_t a_length) const
bool WriteRecordData(const void *a_buf, std::uint32_t a_length) const
bool ResolveFormID(RE::FormID a_oldFormID, RE::FormID &a_newFormID) const
bool OpenRecord(std::uint32_t a_type, std::uint32_t a_version) const
constexpr REL::ID Save(static_cast< std::uint64_t >(34818))
std::uint32_t FormID
Definition: BSCoreTypes.h:5
std::uint32_t VMTypeID
Definition: BSCoreTypes.h:9
std::uint64_t VMHandle
Definition: BSCoreTypes.h:7
BSScript::IFunctionArguments * MakeFunctionArguments(Args &&... a_args)
Definition: FunctionArguments.h:80
VMArg(T &&) -> VMArg< T >
string(const CharT(&)[N]) -> string< CharT, N - 1 >
Definition: API.h:14
typename Impl::EventFilterUnique< Filter >::template RegistrationMapUnique< void, Args... > RegistrationMapUnique
Definition: RegistrationMapUnique.h:694
const TaskInterface * GetTaskInterface() noexcept
Definition: EffectArchetypes.h:65
Definition: RegistrationTraits.h:40