Files
l4d2-internal-base2/l4d2/game/source_engine/netvars.h
2022-10-26 17:08:42 +08:00

89 lines
2.4 KiB
C++

#pragma once
#include <unordered_map>
namespace Game
{
class NetVar_t
{
private:
struct stored_data
{
RecvProp* prop_ptr;
std::uint16_t class_relative_offset;
};
public:
// Return a const instance, others shouldnt modify this.
static auto Get() -> const NetVar_t&
{
static NetVar_t instance;
return instance;
}
auto GetOffset(const fnv::hash hash) const -> std::uint16_t
{
return m_props.at(hash).class_relative_offset;
}
auto GetProP(const fnv::hash hash) const -> RecvProp*
{
return m_props.at(hash).prop_ptr;
}
// Prevent instruction cache pollution caused by automatic
// inlining of `get` and get_offset every netvar usage when
// there are a lot of netvars
__declspec(noinline) static auto GetOffsetByHASH(const fnv::hash hash) -> std::uint16_t
{
return Get().GetOffset(hash);
}
template<fnv::hash Hash>
static auto ToAddress(void* ptr) -> std::uintptr_t
{
static auto offset = std::uint16_t(0);
if (!offset)
offset = GetOffsetByHASH(Hash);
return std::uintptr_t(ptr) + offset;
}
private:
NetVar_t();
auto DUMP_NETVAR(const char* base_class, RecvTable* table, std::uint16_t offset) -> void;
private:
std::unordered_map<fnv::hash, stored_data> m_props;
};
}
#define PNETVAR_OFFSET(funcname, class_name, var_name, offset, ...) \
auto funcname() -> std::add_pointer_t<__VA_ARGS__> \
{ \
constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \
const auto addr = Game::NetVar_t::ToAddress<hash>(this); \
return reinterpret_cast<std::add_pointer_t<__VA_ARGS__>>(addr); \
}
#define PNETVAR(funcname, class_name, var_name, ...) \
PNETVAR_OFFSET(funcname, class_name, var_name, 0, __VA_ARGS__)
#define NETVAR_OFFSET(funcname, class_name, var_name, offset, ...) \
auto funcname() -> std::add_lvalue_reference_t<__VA_ARGS__> \
{ \
constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \
const auto addr = Game::NetVar_t::ToAddress<hash>(this + offset); \
return *reinterpret_cast<std::add_pointer_t<__VA_ARGS__>>(addr); \
}
#define NETVAR(funcname, class_name, var_name, ...) \
NETVAR_OFFSET(funcname, class_name, var_name, 0, __VA_ARGS__)
#define NETPROP(funcname, class_name, var_name) \
static auto funcname() -> RecvProp* \
{ \
constexpr auto hash = fnv::hash_constexpr(class_name "->" var_name); \
static auto prop_ptr = Game::NetVar_t::Get().GetProP(hash); \
return prop_ptr; \
}