Files
native_invoker_v2/include/fxn/invoker.hpp
2025-11-13 20:56:11 +01:00

92 lines
2.5 KiB
C++

#pragma once
#include <string_view>
#include <cstdint>
#include <functional>
#include <fxn/context.hpp>
namespace fxn
{
inline constexpr char ToLower(const char c) noexcept
{
return (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
}
inline constexpr unsigned int HashString(std::string_view str) noexcept
{
uint32_t hash = 0;
for (char ch : str)
{
hash += ToLower(ch);
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
class NativeInvoker
{
public:
static NativeInvoker& GetInstance();
static void AddTickEvent(const std::function<void()>& callback);
public:
void Initialize();
public:
/**
* @brief Invokes the native on current thread
* @note MAYBE UNSAFE IF NOT ON GAME THREAD
* @param hash native hash to invoke
* @param context native context to use
* @return whether the native could be found and executed
*/
bool Invoke(fxn::NativeContext* context);
/**
* @brief Invokes the native on a special game thread
* @param hash native hash to invoke
* @param context native context to use
* @return whether the native could be found and executed
*/
bool Schedule(fxn::NativeContext* context, bool waitForCompletion = true);
public:
template<typename R, typename... Args>
R Invoke(std::uint64_t hash, Args&&... args)
{
fxn::NativeContext context { hash };
(context.PushArgument(std::forward<Args>(args)), ...);
Invoke(&context);
if constexpr (!std::is_same_v<R, void>)
{
return context.GetResult<R>();
}
}
template<typename R, typename... Args>
R Schedule(std::uint64_t hash, Args&&... args)
{
fxn::NativeContext context { hash };
(context.PushArgument(std::forward<Args>(args)), ...);
Schedule(&context, true);
if constexpr (!std::is_same_v<R, void>)
{
return context.GetResult<R>();
}
}
public:
void HookNative(std::uint64_t hash, std::function<bool(fxn::NativeContext* context, bool& shouldCallOriginal)> hook);
};
}