CommonLibSSE NG
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 args = RE::MakeFunctionArguments(std::forward<Args>(a_args)...);
104 vm->SendEvent(handle, eventName, args);
105 }
106 }
107 }
108 }
109
110 inline void QueueEvent(Filter a_filter, Args... a_args)
111 {
112 std::tuple args(VMArg(std::forward<Args>(a_args))...);
113 auto task = GetTaskInterface();
114 assert(task);
115 if (task) {
116 task->AddTask([a_filter, args, this]() mutable {
117 SendEvent_Tuple(std::move(a_filter), std::move(args), index_sequence_for_tuple<decltype(args)>{});
118 });
119 }
120 }
121
122 private:
123 template <class Tuple, std::size_t... I>
124 inline void SendEvent_Tuple(Filter a_filter, Tuple&& a_tuple, std::index_sequence<I...>)
125 {
126 SendEvent(a_filter, std::get<I>(std::forward<Tuple>(a_tuple)).Unpack()...);
127 }
128 };
129
130 template <>
132 {
133 private:
135
136 public:
137 RegistrationMap() = delete;
140
141 inline RegistrationMap(const std::string_view& a_eventName) :
142 super(a_eventName)
143 {}
144
145 ~RegistrationMap() = default;
146
149
150 inline void SendEvent(Filter a_filter)
151 {
152 RE::BSFixedString eventName(this->_eventName);
153
155 if (auto it = this->_regs.find(a_filter); it != this->_regs.end()) {
156 for (auto& handle : it->second) {
157 auto args = RE::MakeFunctionArguments();
158 vm->SendEvent(handle, eventName, args);
159 }
160 }
161 }
162 }
163
164 inline void QueueEvent(Filter a_filter)
165 {
166 auto task = GetTaskInterface();
167 assert(task);
168 task->AddTask([a_filter, this]() {
169 SendEvent(std::move(a_filter));
170 });
171 }
172 };
173 };
174
175 template <class Filter>
177 _regs(),
178 _eventName(a_eventName),
179 _lock()
180 {}
181
182 template <class Filter>
184 _regs(),
185 _eventName(a_rhs._eventName),
186 _lock()
187 {
188 a_rhs._lock.lock();
189 _regs = a_rhs._regs;
190 a_rhs._lock.unlock();
191
193 if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
194 for (auto& reg : _regs) {
195 for (auto& handle : reg.second) {
196 policy->PersistHandle(handle);
197 }
198 }
199 }
200 }
201
202 template <class Filter>
204 _regs(),
205 _eventName(a_rhs._eventName),
206 _lock()
207 {
208 Locker locker(a_rhs._lock);
209 _regs = std::move(a_rhs._regs);
210 a_rhs._regs.clear();
211 }
212
213 template <class Filter>
215 {
217 if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
218 for (auto& reg : _regs) {
219 for (auto& handle : reg.second) {
220 policy->ReleaseHandle(handle);
221 }
222 }
223 }
224 }
225
226 template <class Filter>
228 {
229 if (this == &a_rhs) {
230 return *this;
231 }
232
233 Locker lhsLocker(_lock);
234 Clear();
235
236 {
237 Locker rhsLocker(a_rhs._lock);
238 _regs = a_rhs._regs;
239 _eventName = a_rhs._eventName;
240 }
241
243 if (auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr) {
244 for (auto& reg : _regs) {
245 for (auto& handle : reg.second) {
246 policy->PersistHandle(handle);
247 }
248 }
249 }
250
251 return *this;
252 }
253
254 template <class Filter>
256 {
257 if (this == &a_rhs) {
258 return *this;
259 }
260
261 Locker lhsLocker(_lock);
262 Locker rhsLocker(a_rhs._lock);
263
264 Clear();
265
266 _eventName = a_rhs._eventName;
267
268 _regs = std::move(a_rhs._regs);
269 a_rhs._regs.clear();
270
271 return *this;
272 }
273
274 template <class Filter>
276 {
277 assert(a_form);
278 return Register(a_form, std::move(a_filter), static_cast<RE::VMTypeID>(a_form->GetFormType()));
279 }
280
281 template <class Filter>
283 {
284 assert(a_alias);
285 return Register(a_alias, std::move(a_filter), a_alias->GetVMTypeID());
286 }
287
288 template <class Filter>
289 bool EventFilter<Filter>::RegistrationMapBase::Register(const RE::ActiveEffect* a_activeEffect, Filter a_filter)
290 {
291 assert(a_activeEffect);
292 return Register(a_activeEffect, std::move(a_filter), RE::ActiveEffect::VMTYPEID);
293 }
294
295 template <class Filter>
297 {
298 assert(a_form);
299 return Unregister(a_form, std::move(a_filter), static_cast<RE::VMTypeID>(a_form->GetFormType()));
300 }
301
302 template <class Filter>
304 {
305 assert(a_alias);
306 return Unregister(a_alias, std::move(a_filter), a_alias->GetVMTypeID());
307 }
308
309 template <class Filter>
311 {
312 assert(a_activeEffect);
313 return Unregister(a_activeEffect, std::move(a_filter), RE::ActiveEffect::VMTYPEID);
314 }
315
316 template <class Filter>
318 {
319 assert(a_form);
320 UnregisterAll(a_form, static_cast<RE::VMTypeID>(a_form->GetFormType()));
321 }
322
323 template <class Filter>
325 {
326 assert(a_alias);
327 UnregisterAll(a_alias, a_alias->GetVMTypeID());
328 }
329
330 template <class Filter>
332 {
333 assert(a_activeEffect);
334 UnregisterAll(a_activeEffect, RE::ActiveEffect::VMTYPEID);
335 }
336
337 template <class Filter>
339 {
341 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
342 if (!policy) {
343 log::error("Failed to get handle policy!");
344 return;
345 }
346
347 Locker locker(_lock);
348 for (auto& reg : _regs) {
349 if (auto result = reg.second.erase(a_handle); result != 0) {
350 policy->ReleaseHandle(a_handle);
351 }
352 }
353 }
354
355 template <class Filter>
357 {
359 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
360 Locker locker(_lock);
361 if (policy) {
362 for (auto& reg : _regs) {
363 for (auto& handle : reg.second) {
364 policy->ReleaseHandle(handle);
365 }
366 }
367 }
368 _regs.clear();
369 }
370
371 template <class Filter>
372 bool EventFilter<Filter>::RegistrationMapBase::Save(SerializationInterface* a_intfc, std::uint32_t a_type, std::uint32_t a_version)
373 {
374 assert(a_intfc);
375 if (!a_intfc->OpenRecord(a_type, a_version)) {
376 log::error("Failed to open record!");
377 return false;
378 }
379
380 return Save(a_intfc);
381 }
382
383 template <class Filter>
385 {
386 if constexpr (std::is_same_v<std::string, Filter>) {
387 std::size_t length = a_filter.length() + 1;
388 if (!a_intfc->WriteRecordData(length) || !a_intfc->WriteRecordData(a_filter.c_str(), static_cast<std::uint32_t>(length))) {
389 return false;
390 }
391 return true;
392 } else {
393 return a_intfc->WriteRecordData(a_filter);
394 }
395 }
396
397 template <class Filter>
399 {
400 assert(a_intfc);
401 Locker locker(_lock);
402
403 // Reg count
404 const std::size_t numRegs = _regs.size();
405 if (!a_intfc->WriteRecordData(numRegs)) {
406 log::error("Failed to save reg count ({})!", numRegs);
407 return false;
408 }
409
410 for (auto& reg : _regs) {
411 // filter
412 if (!SaveFilter(a_intfc, reg.first)) {
413 return false;
414 }
415 // Handle count
416 std::size_t numHandles = reg.second.size();
417 if (!a_intfc->WriteRecordData(numHandles)) {
418 log::error("Failed to save handle count ({})!", numHandles);
419 return false;
420 }
421 // Handle
422 for (auto& handle : reg.second) {
423 if (!a_intfc->WriteRecordData(handle)) {
424 log::error("Failed to save handle ({})", handle);
425 return false;
426 }
427 }
428 }
429
430 return true;
431 }
432
433 template <class Filter>
435 {
436 if constexpr (std::is_same_v<std::string, Filter>) {
437 std::size_t length = 0;
438 if (!a_intfc->ReadRecordData(length)) {
439 return false;
440 }
441 a_filter.reserve(length);
442 return a_intfc->ReadRecordData(a_filter.data(), static_cast<std::uint32_t>(length));
443 } else if constexpr (std::is_same_v<RE::FormID, Filter>) {
444 if (!a_intfc->ReadRecordData(a_filter)) {
445 return false;
446 }
447 return a_intfc->ResolveFormID(a_filter, a_filter);
448 } else {
449 return a_intfc->ReadRecordData(a_filter);
450 }
451 }
452
453 template <class Filter>
455 {
456 assert(a_intfc);
457 std::size_t numRegs;
458 a_intfc->ReadRecordData(numRegs);
459
460 Locker locker(_lock);
461 _regs.clear();
462
463 Filter filter{};
464 // Handle count
465 std::size_t numHandles;
466 // Handle
467 RE::VMHandle handle;
468
469 for (std::size_t i = 0; i < numRegs; ++i) {
470 if (!LoadFilter(a_intfc, filter)) {
471 return false;
472 }
473 a_intfc->ReadRecordData(numHandles);
474 for (std::size_t j = 0; j < numHandles; ++j) {
475 a_intfc->ReadRecordData(handle);
476 if (a_intfc->ResolveHandle(handle, handle)) {
477 _regs[filter].insert(handle);
478 }
479 }
480 }
481
482 return true;
483 }
484
485 template <class Filter>
487 {
488 Clear();
489 }
490
491 template <class Filter>
492 bool EventFilter<Filter>::RegistrationMapBase::Register(const void* a_object, Filter a_filter, RE::VMTypeID a_typeID)
493 {
494 assert(a_object);
496 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
497 if (!policy) {
498 log::error("Failed to get handle policy!");
499 return false;
500 }
501
502 const auto invalidHandle = policy->EmptyHandle();
503 auto handle = policy->GetHandleForObject(a_typeID, a_object);
504 if (handle == invalidHandle) {
505 log::error("Failed to create handle!");
506 return false;
507 }
508
509 _lock.lock();
510 auto result = _regs[a_filter].insert(handle);
511 _lock.unlock();
512
513 if (result.second) {
514 policy->PersistHandle(handle);
515 }
516
517 return result.second;
518 }
519
520 template <class Filter>
521 bool EventFilter<Filter>::RegistrationMapBase::Unregister(const void* a_object, Filter a_filter, RE::VMTypeID a_typeID)
522 {
523 assert(a_object);
525 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
526 if (!policy) {
527 log::error("Failed to get handle policy!");
528 return false;
529 }
530
531 const auto invalidHandle = policy->EmptyHandle();
532 const auto handle = policy->GetHandleForObject(a_typeID, a_object);
533 if (handle == invalidHandle) {
534 log::error("Failed to create handle!");
535 return false;
536 }
537
538 Locker locker(_lock);
539 if (auto it = _regs.find(a_filter); it != _regs.end()) {
540 if (auto result = it->second.erase(handle); result != 0) {
541 policy->ReleaseHandle(handle);
542 return true;
543 }
544 }
545
546 return false;
547 }
548
549 template <class Filter>
551 {
552 assert(a_object);
554 auto policy = vm ? vm->GetObjectHandlePolicy() : nullptr;
555 if (!policy) {
556 log::error("Failed to get handle policy!");
557 return;
558 }
559
560 const auto invalidHandle = policy->EmptyHandle();
561 const auto handle = policy->GetHandleForObject(a_typeID, a_object);
562 if (handle == invalidHandle) {
563 log::error("Failed to create handle!");
564 return;
565 }
566
567 Locker locker(_lock);
568 for (auto& reg : _regs) {
569 if (auto result = reg.second.erase(handle); result != 0) {
570 policy->ReleaseHandle(handle);
571 }
572 }
573 }
574 }
575
576 template <class Filter, class... Args>
578}
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:35
FormType GetFormType() const noexcept
Definition TESForm.h:288
RegistrationMap & operator=(const RegistrationMap &)=default
void QueueEvent(Filter a_filter)
Definition RegistrationMap.h:164
RegistrationMap(const RegistrationMap &)=default
void SendEvent(Filter a_filter)
Definition RegistrationMap.h:150
RegistrationMap(const std::string_view &a_eventName)
Definition RegistrationMap.h:141
RegistrationMap & operator=(RegistrationMap &&)=default
Definition RegistrationMap.h:25
bool Load(SerializationInterface *a_intfc)
Definition RegistrationMap.h:454
RegistrationMapBase & operator=(const RegistrationMapBase &a_rhs)
Definition RegistrationMap.h:227
bool LoadFilter(SerializationInterface *a_intfc, Filter &a_filter)
Definition RegistrationMap.h:434
bool Unregister(const RE::TESForm *a_form, Filter a_filter)
Definition RegistrationMap.h:296
void Revert(SerializationInterface *)
Definition RegistrationMap.h:486
~RegistrationMapBase()
Definition RegistrationMap.h:214
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:275
bool SaveFilter(SerializationInterface *a_intfc, Filter a_filter)
Definition RegistrationMap.h:384
void Clear()
Definition RegistrationMap.h:356
std::recursive_mutex Lock
Definition RegistrationMap.h:53
void UnregisterAll(const RE::TESForm *a_form)
Definition RegistrationMap.h:317
bool Save(SerializationInterface *a_intfc, std::uint32_t a_type, std::uint32_t a_version)
Definition RegistrationMap.h:372
Definition RegistrationMap.h:69
Definition RegistrationMap.h:22
Definition RegistrationTraits.h:45
Definition Interfaces.h:71
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:577
const TaskInterface * GetTaskInterface() noexcept
Definition ActorValueList.h:28
Definition RegistrationTraits.h:40