CommonLibSSE (powerof3)
Loading...
Searching...
No Matches
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"
8#include "RE/T/TESForm.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
18namespace 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;
69 std::string _eventName;
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 copy = std::make_tuple(a_args...);
112 std::apply([&](auto&&... a_copy) {
113 auto args = RE::MakeFunctionArguments(std::forward<Args>(a_copy)...);
114 vm->SendEvent(handle, eventName, args);
115 },
116 copy);
117 }
118 }
119 }
120 }
121 }
122 }
123
124 inline void QueueEvent(RE::TESObjectREFR* a_target, PassFilterFunc a_callback, Args... a_args)
125 {
126 std::tuple args(VMArg(std::forward<Args>(a_args))...);
127 auto task = GetTaskInterface();
128 assert(task);
129 if (task) {
130 task->AddTask([a_target, a_callback, args, this]() mutable {
131 SendEvent_Tuple(a_target, a_callback, std::move(args), index_sequence_for_tuple<decltype(args)>{});
132 });
133 }
134 }
135
136 private:
137 template <class Tuple, std::size_t... I>
138 inline void SendEvent_Tuple(RE::TESObjectREFR* a_target, PassFilterFunc a_callback, Tuple&& a_tuple, std::index_sequence<I...>)
139 {
140 SendEvent(a_target, a_callback, std::get<I>(std::forward<Tuple>(a_tuple)).Unpack()...);
141 }
142 };
143
144 template <>
146 {
147 private:
149
150 public:
154
155 inline RegistrationMapUnique(const std::string_view& a_eventName) :
156 super(a_eventName)
157 {}
158
160
163
164 inline void SendEvent(const RE::TESObjectREFR* a_target, PassFilterFunc a_callback)
165 {
166 RE::BSFixedString eventName(this->_eventName);
167
169 const auto targetFormID = a_target->GetFormID();
170 if (auto it = this->_regs.find(targetFormID); it != this->_regs.end()) {
171 for (auto& [eventFilter, handles] : it->second) {
172 if (a_callback(eventFilter.first, eventFilter.second)) {
173 for (auto& handle : handles) {
174 auto args = RE::MakeFunctionArguments();
175 vm->SendEvent(handle, eventName, args);
176 }
177 }
178 }
179 }
180 }
181 }
182
183 inline void QueueEvent(RE::TESObjectREFR* a_target, PassFilterFunc a_callback)
184 {
185 auto task = GetTaskInterface();
186 assert(task);
187 task->AddTask([a_target, a_callback, this]() {
188 SendEvent(a_target, std::move(a_callback));
189 });
190 }
191 };
192 };
193
194 template <class Filter>
196 _regs(),
197 _eventName(a_eventName),
198 _lock()
199 {}
200
201 template <class Filter>
203 _regs(),
204 _eventName(a_rhs._eventName),
205 _lock()
206 {
207 a_rhs._lock.lock();
208 _regs = a_rhs._regs;
209 a_rhs._lock.unlock();
210
212 if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
213 for (auto& reg : _regs) {
214 for (auto& keyHandles : reg.second) {
215 for (auto& handle : keyHandles.second) {
216 policy->PersistHandle(handle);
217 }
218 }
219 }
220 }
221 }
222
223 template <class Filter>
225 _regs(),
226 _eventName(a_rhs._eventName),
227 _lock()
228 {
229 Locker locker(a_rhs._lock);
230 _regs = std::move(a_rhs._regs);
231 a_rhs._regs.clear();
232 }
233
234 template <class Filter>
236 {
238 if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
239 for (auto& reg : _regs) {
240 for (auto& keyHandles : reg.second) {
241 for (auto& handle : keyHandles.second) {
242 policy->ReleaseHandle(handle);
243 }
244 }
245 }
246 }
247 }
248
249 template <class Filter>
251 {
252 if (this == &a_rhs) {
253 return *this;
254 }
255
256 Locker lhsLocker(_lock);
257 Clear();
258
259 {
260 Locker rhsLocker(a_rhs._lock);
261 _regs = a_rhs._regs;
262 _eventName = a_rhs._eventName;
263 }
264
266 if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
267 for (auto& reg : _regs) {
268 for (auto& keyHandles : reg.second) {
269 for (auto& handle : keyHandles.second) {
270 policy->PersistHandle(handle);
271 }
272 }
273 }
274 }
275
276 return *this;
277 }
278
279 template <class Filter>
281 {
282 if (this == &a_rhs) {
283 return *this;
284 }
285
286 Locker lhsLocker(_lock);
287 Locker rhsLocker(a_rhs._lock);
288
289 Clear();
290
291 _eventName = a_rhs._eventName;
292
293 _regs = std::move(a_rhs._regs);
294 a_rhs._regs.clear();
295
296 return *this;
297 }
298
299 template <class Filter>
300 bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Register(RE::TESForm* a_form, const Filter& a_filter, bool a_matchFilter)
301 {
302 assert(a_form);
303
304 const auto reference = a_form->AsReference();
305 const auto formID = reference ? reference->GetFormID() : 0;
306
307 if (formID != 0) {
308 return Register(a_form, formID, { a_filter, a_matchFilter }, static_cast<RE::VMTypeID>(a_form->GetFormType()));
309 }
310
311 return false;
312 }
313
314 template <class Filter>
315 bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Register(RE::ActiveEffect* a_activeEffect, const Filter& a_filter, bool a_matchFilter)
316 {
317 assert(a_activeEffect);
318
319 const auto target = a_activeEffect->GetTargetActor();
320 const auto formID = target ? target->GetFormID() : 0;
321
322 if (formID != 0) {
323 return Register(a_activeEffect, formID, { a_filter, a_matchFilter }, RE::ActiveEffect::VMTYPEID);
324 }
325
326 return false;
327 }
328
329 template <class Filter>
330 bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Register(RE::BGSRefAlias* a_alias, const Filter& a_filter, bool a_matchFilter)
331 {
332 assert(a_alias);
333
334 const auto target = a_alias->GetActorReference();
335 const auto formID = target ? target->GetFormID() : 0;
336
337 if (formID != 0) {
338 return Register(a_alias, formID, { a_filter, a_matchFilter }, RE::BGSRefAlias::VMTYPEID);
339 }
340
341 return false;
342 }
343
344 template <class Filter>
345 bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Unregister(RE::TESForm* a_form, const Filter& a_filter, bool a_matchFilter)
346 {
347 assert(a_form);
348
349 const auto reference = a_form->AsReference();
350 const auto formID = reference ? reference->GetFormID() : 0;
351
352 if (formID != 0) {
353 return Unregister(a_form, formID, { a_filter, a_matchFilter }, static_cast<RE::VMTypeID>(a_form->GetFormType()));
354 }
355
356 return false;
357 }
358
359 template <class Filter>
360 bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Unregister(RE::ActiveEffect* a_activeEffect, const Filter& a_filter, bool a_matchFilter)
361 {
362 assert(a_activeEffect);
363
364 const auto target = a_activeEffect->GetTargetActor();
365 const auto formID = target ? target->GetFormID() : 0;
366
367 if (formID != 0) {
368 return Unregister(a_activeEffect, formID, { a_filter, a_matchFilter }, RE::ActiveEffect::VMTYPEID);
369 }
370
371 return false;
372 }
373
374 template <class Filter>
375 bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Unregister(RE::BGSRefAlias* a_alias, const Filter& a_filter, bool a_matchFilter)
376 {
377 assert(a_alias);
378
379 const auto target = a_alias->GetActorReference();
380 const auto formID = target ? target->GetFormID() : 0;
381
382 if (formID != 0) {
383 return Unregister(a_alias, formID, { a_filter, a_matchFilter }, RE::BGSRefAlias::VMTYPEID);
384 }
385
386 return false;
387 }
388
389 template <class Filter>
391 {
392 assert(a_form);
393
394 const auto reference = a_form->AsReference();
395 const auto formID = reference ? reference->GetFormID() : 0;
396
397 if (formID != 0) {
398 UnregisterAll(a_form, formID, static_cast<RE::VMTypeID>(a_form->GetFormType()));
399 }
400 }
401
402 template <class Filter>
404 {
405 assert(a_activeEffect);
406
407 const auto target = a_activeEffect->GetTargetActor();
408 const auto formID = target ? target->GetFormID() : 0;
409
410 if (formID != 0) {
411 UnregisterAll(a_activeEffect, formID, RE::ActiveEffect::VMTYPEID);
412 }
413 }
414
415 template <class Filter>
417 {
418 assert(a_alias);
419
420 const auto target = a_alias->GetActorReference();
421 const auto formID = target ? target->GetFormID() : 0;
422
423 if (formID != 0) {
424 UnregisterAll(a_alias, formID, RE::BGSRefAlias::VMTYPEID);
425 }
426 }
427
428 template <class Filter>
430 {
432 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
433 if (!policy) {
434 log::error("Failed to get handle policy!");
435 return;
436 }
437
438 Locker locker(_lock);
439 for (auto& reg : _regs) {
440 for (auto& keyHandle : reg.second) {
441 if (auto result = keyHandle.second.erase(a_handle); result != 0) {
442 policy->ReleaseHandle(a_handle);
443 }
444 }
445 }
446 }
447
448 template <class Filter>
450 {
452 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
453 if (!policy) {
454 log::error("Failed to get handle policy!");
455 return;
456 }
457
458 Locker locker(_lock);
459 auto it = _regs.find(a_uniqueID);
460 if (it != _regs.end()) {
461 for (auto& keyHandles : it->second) {
462 for (auto& handle : keyHandles.second) {
463 policy->ReleaseHandle(handle);
464 }
465 }
466 _regs.erase(it);
467 }
468 }
469
470 template <class Filter>
472 {
474 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
475 Locker locker(_lock);
476 if (policy) {
477 for (auto& reg : _regs) {
478 for (auto& keyHandle : reg.second) {
479 for (auto& handle : keyHandle.second) {
480 policy->ReleaseHandle(handle);
481 }
482 }
483 }
484 }
485 _regs.clear();
486 }
487
488 template <class Filter>
489 bool EventFilterUnique<Filter>::RegistrationMapUniqueBase::Save(SerializationInterface* a_intfc, std::uint32_t a_type, std::uint32_t a_version)
490 {
491 assert(a_intfc);
492 if (!a_intfc->OpenRecord(a_type, a_version)) {
493 log::error("Failed to open record!");
494 return false;
495 }
496
497 return Save(a_intfc);
498 }
499
500 template <class Filter>
502 {
503 assert(a_intfc);
504 Locker locker(_lock);
505
506 // Reg count
507 const std::size_t numRegs = _regs.size();
508 if (!a_intfc->WriteRecordData(numRegs)) {
509 log::error("Failed to save reg count ({})!", numRegs);
510 return false;
511 }
512 for (auto& reg : _regs) {
513 //FormID
514 if (!a_intfc->WriteRecordData(reg.first)) {
515 log::error("Failed to save handle formID ({:X})", reg.first);
516 return false;
517 }
518 std::size_t numUniqueHandle = reg.second.size();
519 if (!a_intfc->WriteRecordData(numUniqueHandle)) {
520 log::error("Failed to save handle count ({})!", numUniqueHandle);
521 return false;
522 }
523 // UniqueHandle
524 for (auto& [key, handles] : reg.second) {
525 // EventFilter
526 auto [eventFilter, match] = key;
527 if (!eventFilter.Save(a_intfc)) {
528 log::error("Failed to save event filters!");
529 return false;
530 }
531 if (!a_intfc->WriteRecordData(match)) {
532 log::error("Failed to save reg key as bool ({})!", match);
533 return false;
534 }
535 //handle set
536 std::size_t numHandles = handles.size();
537 if (!a_intfc->WriteRecordData(numHandles)) {
538 log::error("Failed to save handle count ({})!", numHandles);
539 return false;
540 }
541 for (auto& handle : handles) {
542 if (!a_intfc->WriteRecordData(handle)) {
543 log::error("Failed to save handle ({})", handle);
544 return false;
545 }
546 }
547 }
548 }
549
550 return true;
551 }
552
553 template <class Filter>
555 {
556 assert(a_intfc);
557 std::size_t numRegs;
558 a_intfc->ReadRecordData(numRegs);
559
560 Locker locker(_lock);
561 _regs.clear();
562
563 //FormID
564 RE::FormID formID;
565 // KeyHandle
566 std::size_t numKeyHandle;
567 // Handle
568 std::size_t numHandles;
569 RE::VMHandle vmHandle;
570
571 for (std::size_t i = 0; i < numRegs; ++i) {
572 a_intfc->ReadRecordData(formID);
573 if (!a_intfc->ResolveFormID(formID, formID)) {
574 log::warn("Failed to resolve target formID ({:X})", formID);
575 continue;
576 }
577 a_intfc->ReadRecordData(numKeyHandle);
578 for (std::size_t j = 0; j < numKeyHandle; ++j) {
579 // filter
580 Filter eventFilter{};
581 if (!eventFilter.Load(a_intfc)) {
582 log::error("Failed to save event filters!");
583 continue;
584 }
585 bool match;
586 a_intfc->ReadRecordData(match);
587 EventFilter curKey = { eventFilter, match };
588 // handles
589 a_intfc->ReadRecordData(numHandles);
590 for (std::size_t k = 0; k < numHandles; ++k) {
591 a_intfc->ReadRecordData(vmHandle);
592 if (a_intfc->ResolveHandle(vmHandle, vmHandle)) {
593 _regs[formID][curKey].insert(vmHandle);
594 }
595 }
596 }
597 }
598
599 return true;
600 }
601
602 template <class Filter>
607
608 template <class Filter>
610 {
611 assert(a_object);
613 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
614 if (!policy) {
615 log::error("Failed to get handle policy!");
616 return false;
617 }
618
619 const auto invalidHandle = policy->EmptyHandle();
620 auto handle = policy->GetHandleForObject(a_typeID, a_object);
621 if (handle == invalidHandle) {
622 log::error("Failed to create handle!");
623 return false;
624 }
625
626 _lock.lock();
627 auto result = _regs[a_formID][a_filter].insert(handle);
628 _lock.unlock();
629
630 if (result.second) {
631 policy->PersistHandle(handle);
632 }
633
634 return result.second;
635 }
636
637 template <class Filter>
639 {
640 assert(a_object);
642 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
643 if (!policy) {
644 log::error("Failed to get handle policy!");
645 return false;
646 }
647
648 const auto invalidHandle = policy->EmptyHandle();
649 const auto handle = policy->GetHandleForObject(a_typeID, a_object);
650 if (handle == invalidHandle) {
651 log::error("Failed to create handle!");
652 return false;
653 }
654
655 Locker locker(_lock);
656 if (auto formIt = _regs.find(a_formID); formIt != _regs.end()) {
657 if (auto keyIt = formIt->second.find(a_filter); keyIt != formIt->second.end()) {
658 if (auto result = keyIt->second.erase(handle); result != 0) {
659 policy->ReleaseHandle(handle);
660 return true;
661 }
662 }
663 }
664
665 return false;
666 }
667
668 template <class Filter>
670 {
671 assert(a_object);
673 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
674 if (!policy) {
675 log::error("Failed to get handle policy!");
676 return;
677 }
678
679 const auto invalidHandle = policy->EmptyHandle();
680 const auto handle = policy->GetHandleForObject(a_typeID, a_object);
681 if (handle == invalidHandle) {
682 log::error("Failed to create handle!");
683 return;
684 }
685
686 Locker locker(_lock);
687 if (auto it = _regs.find(a_formID); it != _regs.end()) {
688 for (auto& keyHandles : it->second) {
689 if (auto result = keyHandles.second.erase(handle); result != 0) {
690 policy->ReleaseHandle(handle);
691 }
692 }
693 }
694 }
695 }
696
697 template <class Filter, class... Args>
699}
Definition ActiveEffect.h:27
static constexpr auto VMTYPEID
Definition ActiveEffect.h:31
Actor * GetTargetActor()
Definition BGSRefAlias.h:15
Actor * GetActorReference() const
static constexpr auto VMTYPEID
Definition BGSRefAlias.h:19
static VirtualMachine * GetSingleton()
Definition TESForm.h:36
FormType GetFormType() const noexcept
Definition TESForm.h:290
FormID GetFormID() const noexcept
Definition TESForm.h:289
TESObjectREFR * AsReference()
Definition TESForm.h:271
Definition TESObjectREFR.h:114
std::recursive_mutex Lock
Definition RegistrationMapUnique.h:61
bool Load(SerializationInterface *a_intfc)
Definition RegistrationMapUnique.h:554
void Clear()
Definition RegistrationMapUnique.h:471
~RegistrationMapUniqueBase()
Definition RegistrationMapUnique.h:235
void Revert(SerializationInterface *)
Definition RegistrationMapUnique.h:603
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:300
bool Save(SerializationInterface *a_intfc, std::uint32_t a_type, std::uint32_t a_version)
Definition RegistrationMapUnique.h:489
RegistrationMapUniqueBase & operator=(const RegistrationMapUniqueBase &a_rhs)
Definition RegistrationMapUnique.h:250
bool Unregister(RE::TESForm *a_form, const Filter &a_filter, bool a_matchFilter)
Definition RegistrationMapUnique.h:345
void UnregisterAll(const RE::TESForm *a_form)
Definition RegistrationMapUnique.h:390
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:124
RegistrationMapUnique(const RegistrationMapUnique &)=default
RegistrationMapUnique & operator=(const RegistrationMapUnique &)=default
void SendEvent(const RE::TESObjectREFR *a_target, PassFilterFunc a_callback)
Definition RegistrationMapUnique.h:164
RegistrationMapUnique(const std::string_view &a_eventName)
Definition RegistrationMapUnique.h:155
void QueueEvent(RE::TESObjectREFR *a_target, PassFilterFunc a_callback)
Definition RegistrationMapUnique.h:183
RegistrationMapUnique & operator=(RegistrationMapUnique &&)=default
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 RegistrationTraits.h:45
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
BSScript::IFunctionArguments * MakeFunctionArguments()
Definition FunctionArguments.h:86
std::uint32_t FormID
Definition BSCoreTypes.h:5
std::uint32_t VMTypeID
Definition BSCoreTypes.h:9
std::uint64_t VMHandle
Definition BSCoreTypes.h:7
Definition API.h:14
typename Impl::EventFilterUnique< Filter >::template RegistrationMapUnique< void, Args... > RegistrationMapUnique
Definition RegistrationMapUnique.h:698
const TaskInterface * GetTaskInterface() noexcept
Definition EffectArchetypes.h:65
Definition RegistrationTraits.h:40