#pragma once #include "RE/N/NiPointer.h" namespace RE { class HandleManager; template class BSUntypedPointerHandle; template > class BSPointerHandle; template class BSPointerHandleManagerInterface; template class BSUntypedPointerHandle { public: using HandleType = std::uint32_t; enum : std::uint32_t { kFreeListBits = FREE_LIST_BITS, kAgeShift = AGE_SHIFT, }; BSUntypedPointerHandle() noexcept = default; BSUntypedPointerHandle(const BSUntypedPointerHandle&) noexcept = default; explicit BSUntypedPointerHandle(HandleType a_handle) noexcept : _handle(a_handle) {} ~BSUntypedPointerHandle() noexcept { reset(); } BSUntypedPointerHandle& operator=(const BSUntypedPointerHandle&) noexcept = default; BSUntypedPointerHandle& operator=(HandleType a_rhs) noexcept { _handle = a_rhs; return *this; } [[nodiscard]] explicit operator bool() const noexcept { return has_value(); } [[nodiscard]] bool has_value() const noexcept { return _handle != 0; } [[nodiscard]] HandleType value() const noexcept { return _handle; } void reset() noexcept { _handle = 0; } [[nodiscard]] friend bool operator==(const BSUntypedPointerHandle& a_lhs, const BSUntypedPointerHandle& a_rhs) noexcept { return a_lhs.value() == a_rhs.value(); } private: // members HandleType _handle{ 0 }; // 0 }; extern template class BSUntypedPointerHandle<>; template class BSPointerHandle { public: BSPointerHandle() noexcept = default; template BSPointerHandle(BSPointerHandle a_rhs) noexcept requires(std::convertible_to) : _handle(a_rhs._handle) {} template explicit BSPointerHandle(Y* a_rhs) requires(std::convertible_to) { get_handle(a_rhs); } ~BSPointerHandle() noexcept = default; template BSPointerHandle& operator=(BSPointerHandle a_rhs) noexcept requires(std::convertible_to) { _handle = a_rhs._handle; return *this; } template BSPointerHandle& operator=(Y* a_rhs) requires(std::convertible_to) { get_handle(a_rhs); return *this; } void reset() noexcept { _handle.reset(); } [[nodiscard]] NiPointer get() const { return BSPointerHandleManagerInterface::GetSmartPointer(*this); } [[nodiscard]] Handle::HandleType get_handle() noexcept { return _handle.value(); } [[nodiscard]] explicit operator bool() const noexcept { return _handle.has_value(); } [[nodiscard]] friend bool operator==(const BSPointerHandle& a_lhs, const BSPointerHandle& a_rhs) noexcept { return a_lhs._handle == a_rhs._handle; } [[nodiscard]] NiPointer operator*() const noexcept { assert(static_cast(*this)); return get(); } [[nodiscard]] NiPointer operator->() const noexcept { assert(static_cast(*this)); return get(); } private: template friend class BSPointerHandle; Handle _handle; // 00 }; extern template class BSPointerHandle; extern template class BSPointerHandle; extern template class BSPointerHandle; using ActorHandle = BSPointerHandle; using ProjectileHandle = BSPointerHandle; using ObjectRefHandle = BSPointerHandle; template struct BSCRC32> { public: [[nodiscard]] std::uint32_t operator()(const BSPointerHandle& a_handle) const noexcept { return BSCRC32::native_handle_type>()(a_handle.native_handle()); } }; template class BSPointerHandleManagerInterface { public: static BSPointerHandle CreateHandle(T* a_ptr) { using func_t = decltype(&BSPointerHandleManagerInterface::CreateHandle); static REL::Relocation func{ ID::BSPointerHandle::BSPointerHandleManagerInterface::CreateHandle }; return func(a_ptr); } static BSPointerHandle GetHandle(T* a_ptr) { using func_t = decltype(&BSPointerHandleManagerInterface::GetHandle); static REL::Relocation func{ ID::BSPointerHandle::BSPointerHandleManagerInterface::GetHandle }; return func(a_ptr); } static bool GetSmartPointer(const BSPointerHandle& a_in, NiPointer& a_out) { using func_t = bool (*)(const BSPointerHandle& a_in, NiPointer& a_out); static REL::Relocation func{ ID::BSPointerHandle::BSPointerHandleManagerInterface::GetSmartPointer }; return func(a_in, a_out); } static NiPointer GetSmartPointer(const BSPointerHandle& a_in) { NiPointer out; GetSmartPointer(a_in, out); return out; } }; extern template class BSPointerHandleManagerInterface; extern template class BSPointerHandleManagerInterface; extern template class BSPointerHandleManagerInterface; }