CommonLibVR
Loading...
Searching...
No Matches
RegistrationMap.h
Go to the documentation of this file.
1#pragma once
2
3#include "RE/A/ActiveEffect.h"
4#include "RE/B/BGSBaseAlias.h"
8#include "RE/T/TESForm.h"
9#include "RE/T/TypeTraits.h"
10#include "RE/V/VirtualMachine.h"
11
12#include "SKSE/API.h"
14#include "SKSE/Interfaces.h"
15
16namespace SKSE
17{
18 namespace Impl
19 {
20 template <class Filter>
22 {
23 public:
25 {
26 public:
28 RegistrationMapBase(const std::string_view& a_eventName);
32
35
36 bool Register(const RE::TESForm* a_form, Filter a_filter);
37 bool Register(const RE::BGSBaseAlias* a_alias, Filter a_filter);
38 bool Register(const RE::ActiveEffect* a_activeEffect, Filter a_filter);
39 bool Unregister(const RE::TESForm* a_form, Filter a_filter);
40 bool Unregister(const RE::BGSBaseAlias* a_alias, Filter a_filter);
41 bool Unregister(const RE::ActiveEffect* a_activeEffect, Filter a_filter);
42 void UnregisterAll(const RE::TESForm* a_form);
43 void UnregisterAll(const RE::BGSBaseAlias* a_alias);
44 void UnregisterAll(const RE::ActiveEffect* a_activeEffect);
45 void UnregisterAll(RE::VMHandle a_handle);
46 void Clear();
47 bool Save(SerializationInterface* a_intfc, std::uint32_t a_type, std::uint32_t a_version);
48 bool Save(SerializationInterface* a_intfc);
49 bool Load(SerializationInterface* a_intfc);
51
52 protected:
53 using Lock = std::recursive_mutex;
54 using Locker = std::lock_guard<Lock>;
55
56 bool Register(const void* a_object, Filter a_filter, RE::VMTypeID a_typeID);
57 bool Unregister(const void* a_object, Filter a_filter, RE::VMTypeID a_typeID);
58 void UnregisterAll(const void* a_object, RE::VMTypeID a_typeID);
59
60 bool SaveFilter(SerializationInterface* a_intfc, Filter a_filter);
61 bool LoadFilter(SerializationInterface* a_intfc, Filter& a_filter);
62
63 std::map<Filter, std::set<RE::VMHandle>> _regs;
64 std::string _eventName;
65 mutable Lock _lock;
66 };
67
68 template <class Enable, class... Args>
70
71 template <class... Args>
73 std::enable_if_t<
74 std::conjunction_v<
75 RE::BSScript::is_return_convertible<Args>...>>,
76 Args...> :
78 {
79 private:
81
82 public:
83 RegistrationMap() = delete;
86
87 inline RegistrationMap(const std::string_view& a_eventName) :
88 super(a_eventName)
89 {}
90
91 ~RegistrationMap() = default;
92
95
96 inline void SendEvent(Filter a_filter, Args... a_args)
97 {
98 RE::BSFixedString eventName(this->_eventName);
99
101 if (auto it = this->_regs.find(a_filter); it != this->_regs.end()) {
102 for (auto& handle : it->second) {
103 auto copy = std::make_tuple(a_args...);
104 std::apply([&](auto&&... a_copy) {
105 auto args = RE::MakeFunctionArguments(std::forward<Args>(a_copy)...);
106 vm->SendEvent(handle, eventName, args);
107 },
108 copy);
109 }
110 }
111 }
112 }
113
114 inline void QueueEvent(Filter a_filter, Args... a_args)
115 {
116 std::tuple args(VMArg(std::forward<Args>(a_args))...);
117 auto task = GetTaskInterface();
118 assert(task);
119 if (task) {
120 task->AddTask([a_filter, args, this]() mutable {
121 SendEvent_Tuple(std::move(a_filter), std::move(args), index_sequence_for_tuple<decltype(args)>{});
122 });
123 }
124 }
125
126 private:
127 template <class Tuple, std::size_t... I>
128 inline void SendEvent_Tuple(Filter a_filter, Tuple&& a_tuple, std::index_sequence<I...>)
129 {
130 SendEvent(a_filter, std::get<I>(std::forward<Tuple>(a_tuple)).Unpack()...);
131 }
132 };
133
134 template <>
136 {
137 private:
139
140 public:
141 RegistrationMap() = delete;
144
145 inline RegistrationMap(const std::string_view& a_eventName) :
146 super(a_eventName)
147 {}
148
149 ~RegistrationMap() = default;
150
153
154 inline void SendEvent(Filter a_filter)
155 {
156 RE::BSFixedString eventName(this->_eventName);
157
159 if (auto it = this->_regs.find(a_filter); it != this->_regs.end()) {
160 for (auto& handle : it->second) {
161 auto args = RE::MakeFunctionArguments();
162 vm->SendEvent(handle, eventName, args);
163 }
164 }
165 }
166 }
167
168 inline void QueueEvent(Filter a_filter)
169 {
170 auto task = GetTaskInterface();
171 assert(task);
172 task->AddTask([a_filter, this]() {
173 SendEvent(std::move(a_filter));
174 });
175 }
176 };
177 };
178
179 template <class Filter>
181 _regs(),
182 _eventName(a_eventName),
183 _lock()
184 {}
185
186 template <class Filter>
188 _regs(),
189 _eventName(a_rhs._eventName),
190 _lock()
191 {
192 a_rhs._lock.lock();
193 _regs = a_rhs._regs;
194 a_rhs._lock.unlock();
195
197 if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
198 for (auto& reg : _regs) {
199 for (auto& handle : reg.second) {
200 policy->PersistHandle(handle);
201 }
202 }
203 }
204 }
205
206 template <class Filter>
208 _regs(),
209 _eventName(a_rhs._eventName),
210 _lock()
211 {
212 Locker locker(a_rhs._lock);
213 _regs = std::move(a_rhs._regs);
214 a_rhs._regs.clear();
215 }
216
217 template <class Filter>
219 {
221 if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
222 for (auto& reg : _regs) {
223 for (auto& handle : reg.second) {
224 policy->ReleaseHandle(handle);
225 }
226 }
227 }
228 }
229
230 template <class Filter>
232 {
233 if (this == &a_rhs) {
234 return *this;
235 }
236
237 Locker lhsLocker(_lock);
238 Clear();
239
240 {
241 Locker rhsLocker(a_rhs._lock);
242 _regs = a_rhs._regs;
243 _eventName = a_rhs._eventName;
244 }
245
247 if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
248 for (auto& reg : _regs) {
249 for (auto& handle : reg.second) {
250 policy->PersistHandle(handle);
251 }
252 }
253 }
254
255 return *this;
256 }
257
258 template <class Filter>
260 {
261 if (this == &a_rhs) {
262 return *this;
263 }
264
265 Locker lhsLocker(_lock);
266 Locker rhsLocker(a_rhs._lock);
267
268 Clear();
269
270 _eventName = a_rhs._eventName;
271
272 _regs = std::move(a_rhs._regs);
273 a_rhs._regs.clear();
274
275 return *this;
276 }
277
278 template <class Filter>
280 {
281 assert(a_form);
282 return Register(a_form, std::move(a_filter), static_cast<RE::VMTypeID>(a_form->GetFormType()));
283 }
284
285 template <class Filter>
287 {
288 assert(a_alias);
289 return Register(a_alias, std::move(a_filter), a_alias->GetVMTypeID());
290 }
291
292 template <class Filter>
293 bool EventFilter<Filter>::RegistrationMapBase::Register(const RE::ActiveEffect* a_activeEffect, Filter a_filter)
294 {
295 assert(a_activeEffect);
296 return Register(a_activeEffect, std::move(a_filter), RE::ActiveEffect::VMTYPEID);
297 }
298
299 template <class Filter>
301 {
302 assert(a_form);
303 return Unregister(a_form, std::move(a_filter), static_cast<RE::VMTypeID>(a_form->GetFormType()));
304 }
305
306 template <class Filter>
308 {
309 assert(a_alias);
310 return Unregister(a_alias, std::move(a_filter), a_alias->GetVMTypeID());
311 }
312
313 template <class Filter>
315 {
316 assert(a_activeEffect);
317 return Unregister(a_activeEffect, std::move(a_filter), RE::ActiveEffect::VMTYPEID);
318 }
319
320 template <class Filter>
322 {
323 assert(a_form);
324 UnregisterAll(a_form, static_cast<RE::VMTypeID>(a_form->GetFormType()));
325 }
326
327 template <class Filter>
329 {
330 assert(a_alias);
331 UnregisterAll(a_alias, a_alias->GetVMTypeID());
332 }
333
334 template <class Filter>
336 {
337 assert(a_activeEffect);
338 UnregisterAll(a_activeEffect, RE::ActiveEffect::VMTYPEID);
339 }
340
341 template <class Filter>
343 {
345 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
346 if (!policy) {
347 log::error("Failed to get handle policy!");
348 return;
349 }
350
351 Locker locker(_lock);
352 for (auto& reg : _regs) {
353 if (auto result = reg.second.erase(a_handle); result != 0) {
354 policy->ReleaseHandle(a_handle);
355 }
356 }
357 }
358
359 template <class Filter>
361 {
363 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
364 Locker locker(_lock);
365 if (policy) {
366 for (auto& reg : _regs) {
367 for (auto& handle : reg.second) {
368 policy->ReleaseHandle(handle);
369 }
370 }
371 }
372 _regs.clear();
373 }
374
375 template <class Filter>
376 bool EventFilter<Filter>::RegistrationMapBase::Save(SerializationInterface* a_intfc, std::uint32_t a_type, std::uint32_t a_version)
377 {
378 assert(a_intfc);
379 if (!a_intfc->OpenRecord(a_type, a_version)) {
380 log::error("Failed to open record!");
381 return false;
382 }
383
384 return Save(a_intfc);
385 }
386
387 template <class Filter>
389 {
390 if constexpr (std::is_same_v<std::string, Filter>) {
391 std::size_t length = a_filter.length() + 1;
392 if (!a_intfc->WriteRecordData(length) || !a_intfc->WriteRecordData(a_filter.c_str(), static_cast<std::uint32_t>(length))) {
393 return false;
394 }
395 return true;
396 } else {
397 return a_intfc->WriteRecordData(a_filter);
398 }
399 }
400
401 template <class Filter>
403 {
404 assert(a_intfc);
405 Locker locker(_lock);
406
407 // Reg count
408 const std::size_t numRegs = _regs.size();
409 if (!a_intfc->WriteRecordData(numRegs)) {
410 log::error("Failed to save reg count ({})!", numRegs);
411 return false;
412 }
413
414 for (auto& reg : _regs) {
415 // filter
416 if (!SaveFilter(a_intfc, reg.first)) {
417 return false;
418 }
419 // Handle count
420 std::size_t numHandles = reg.second.size();
421 if (!a_intfc->WriteRecordData(numHandles)) {
422 log::error("Failed to save handle count ({})!", numHandles);
423 return false;
424 }
425 // Handle
426 for (auto& handle : reg.second) {
427 if (!a_intfc->WriteRecordData(handle)) {
428 log::error("Failed to save handle ({})", handle);
429 return false;
430 }
431 }
432 }
433
434 return true;
435 }
436
437 template <class Filter>
439 {
440 if constexpr (std::is_same_v<std::string, Filter>) {
441 std::size_t length = 0;
442 if (!a_intfc->ReadRecordData(length)) {
443 return false;
444 }
445 a_filter.reserve(length);
446 return a_intfc->ReadRecordData(a_filter.data(), static_cast<std::uint32_t>(length));
447 } else if constexpr (std::is_same_v<RE::FormID, Filter>) {
448 if (!a_intfc->ReadRecordData(a_filter)) {
449 return false;
450 }
451 return a_intfc->ResolveFormID(a_filter, a_filter);
452 } else {
453 return a_intfc->ReadRecordData(a_filter);
454 }
455 }
456
457 template <class Filter>
459 {
460 assert(a_intfc);
461 std::size_t numRegs;
462 a_intfc->ReadRecordData(numRegs);
463
464 Locker locker(_lock);
465 _regs.clear();
466
467 Filter filter{};
468 // Handle count
469 std::size_t numHandles;
470 // Handle
471 RE::VMHandle handle;
472
473 for (std::size_t i = 0; i < numRegs; ++i) {
474 if (!LoadFilter(a_intfc, filter)) {
475 return false;
476 }
477 a_intfc->ReadRecordData(numHandles);
478 for (std::size_t j = 0; j < numHandles; ++j) {
479 a_intfc->ReadRecordData(handle);
480 if (a_intfc->ResolveHandle(handle, handle)) {
481 _regs[filter].insert(handle);
482 }
483 }
484 }
485
486 return true;
487 }
488
489 template <class Filter>
494
495 template <class Filter>
496 bool EventFilter<Filter>::RegistrationMapBase::Register(const void* a_object, Filter a_filter, RE::VMTypeID a_typeID)
497 {
498 assert(a_object);
500 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
501 if (!policy) {
502 log::error("Failed to get handle policy!");
503 return false;
504 }
505
506 const auto invalidHandle = policy->EmptyHandle();
507 auto handle = policy->GetHandleForObject(a_typeID, a_object);
508 if (handle == invalidHandle) {
509 log::error("Failed to create handle!");
510 return false;
511 }
512
513 _lock.lock();
514 auto result = _regs[a_filter].insert(handle);
515 _lock.unlock();
516
517 if (result.second) {
518 policy->PersistHandle(handle);
519 }
520
521 return result.second;
522 }
523
524 template <class Filter>
525 bool EventFilter<Filter>::RegistrationMapBase::Unregister(const void* a_object, Filter a_filter, RE::VMTypeID a_typeID)
526 {
527 assert(a_object);
529 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
530 if (!policy) {
531 log::error("Failed to get handle policy!");
532 return false;
533 }
534
535 const auto invalidHandle = policy->EmptyHandle();
536 const auto handle = policy->GetHandleForObject(a_typeID, a_object);
537 if (handle == invalidHandle) {
538 log::error("Failed to create handle!");
539 return false;
540 }
541
542 Locker locker(_lock);
543 if (auto it = _regs.find(a_filter); it != _regs.end()) {
544 if (auto result = it->second.erase(handle); result != 0) {
545 policy->ReleaseHandle(handle);
546 return true;
547 }
548 }
549
550 return false;
551 }
552
553 template <class Filter>
555 {
556 assert(a_object);
558 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
559 if (!policy) {
560 log::error("Failed to get handle policy!");
561 return;
562 }
563
564 const auto invalidHandle = policy->EmptyHandle();
565 const auto handle = policy->GetHandleForObject(a_typeID, a_object);
566 if (handle == invalidHandle) {
567 log::error("Failed to create handle!");
568 return;
569 }
570
571 Locker locker(_lock);
572 for (auto& reg : _regs) {
573 if (auto result = reg.second.erase(handle); result != 0) {
574 policy->ReleaseHandle(handle);
575 }
576 }
577 }
578 }
579
580 template <class Filter, class... Args>
582}
Definition ActiveEffect.h:27
static constexpr auto VMTYPEID
Definition ActiveEffect.h:31
Definition BGSBaseAlias.h:12
VMTypeID GetVMTypeID() const
static VirtualMachine * GetSingleton()
Definition TESForm.h:40
FormType GetFormType() const noexcept
Definition TESForm.h:294
Definition RegistrationMap.h:25
bool Load(SerializationInterface *a_intfc)
Definition RegistrationMap.h:458
RegistrationMapBase & operator=(const RegistrationMapBase &a_rhs)
Definition RegistrationMap.h:231
bool LoadFilter(SerializationInterface *a_intfc, Filter &a_filter)
Definition RegistrationMap.h:438
bool Unregister(const RE::TESForm *a_form, Filter a_filter)
Definition RegistrationMap.h:300
void Revert(SerializationInterface *)
Definition RegistrationMap.h:490
~RegistrationMapBase()
Definition RegistrationMap.h:218
std::string _eventName
Definition RegistrationMap.h:64
std::lock_guard< Lock > Locker
Definition RegistrationMap.h:54
Lock _lock
Definition RegistrationMap.h:65
std::map< Filter, std::set< RE::VMHandle > > _regs
Definition RegistrationMap.h:63
bool Register(const RE::TESForm *a_form, Filter a_filter)
Definition RegistrationMap.h:279
bool SaveFilter(SerializationInterface *a_intfc, Filter a_filter)
Definition RegistrationMap.h:388
void Clear()
Definition RegistrationMap.h:360
std::recursive_mutex Lock
Definition RegistrationMap.h:53
void UnregisterAll(const RE::TESForm *a_form)
Definition RegistrationMap.h:321
bool Save(SerializationInterface *a_intfc, std::uint32_t a_type, std::uint32_t a_version)
Definition RegistrationMap.h:376
RegistrationMap & operator=(const RegistrationMap &)=default
void QueueEvent(Filter a_filter)
Definition RegistrationMap.h:168
RegistrationMap(const RegistrationMap &)=default
void SendEvent(Filter a_filter)
Definition RegistrationMap.h:154
RegistrationMap(const std::string_view &a_eventName)
Definition RegistrationMap.h:145
RegistrationMap & operator=(RegistrationMap &&)=default
Definition RegistrationMap.h:69
Definition RegistrationMap.h:22
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 VMTypeID
Definition BSCoreTypes.h:9
std::uint64_t VMHandle
Definition BSCoreTypes.h:7
Definition API.h:14
typename Impl::EventFilter< Filter >::template RegistrationMap< void, Args... > RegistrationMap
Definition RegistrationMap.h:581
const TaskInterface * GetTaskInterface() noexcept
Definition EffectArchetypes.h:65
Definition RegistrationTraits.h:40