26 return KHook::Action::Override;
28 return KHook::Action::Supersede;
30 return KHook::Action::Ignore;
54template <
template <
class,
class,
class...>
class HookKind,
class Object,
class Ret,
class... Args>
59 template <
class BeforeHandler,
class AfterHandler>
63 static_assert(!std::is_polymorphic_v<InstalledHook>,
"KHook dispatches through a raw member address");
65 !std::is_null_pointer_v<std::decay_t<BeforeHandler>> || !std::is_null_pointer_v<std::decay_t<AfterHandler>>,
66 "a hook with neither handler would install nothing");
69 Hook.AddContext(
this, &InstalledHook::RunBefore, &InstalledHook::RunAfter);
76 using Before = std::move_only_function<HookResult<Ret>(
Object&, Args...)>;
77 using After = std::move_only_function<
void(
Object&, Args...)>;
80 template <
class Handler>
81 static Before WrapBefore(Handler&&
handler)
83 if constexpr (std::is_null_pointer_v<std::decay_t<Handler>>)
87 else if constexpr (std::is_void_v<std::invoke_result_t<std::decay_t<Handler>&,
Object&, Args...>>)
96 return std::forward<Handler>(
handler);
109 _after(*
self, std::forward<Args>(
args)...);
141template <
class Iface,
class Ret,
class... Args,
class Before,
class After = std::nullptr_t>
146 auto hook = std::make_unique<Installed>(std::forward<Before>(
before), std::forward<After>(
after));
167template <
class Object,
class Ret,
class... Args,
class Before,
class After = std::nullptr_t>
173 return std::unexpected(
Error::Unsupported(std::format(
"the {} vtable slot did not bind", name)));
177 auto hook = std::make_unique<Installed>(std::forward<Before>(
before), std::forward<After>(
after));
199template <
class Object,
class Ret,
class... Args,
class Before,
class After = std::nullptr_t>
205 return std::unexpected(
Error::Unsupported(std::format(
"the {} signature did not bind", name)));
209 auto hook = std::make_unique<Installed>(std::forward<Before>(
before), std::forward<After>(
after));
210 hook->Hook.Configure(
static_cast<const void*
>(
function.Ptr()));
217template <
class Iface,
class Ret,
class... Args,
class... Passed>
A hook before-handler's verdict.
InstalledHook(BeforeHandler &&before, AfterHandler &&after)
HookKind< Object, Ret, Args... > Hook
InstalledHook(const InstalledHook &)=delete
InstalledHook & operator=(const InstalledHook &)=delete
Owns one registration and releases it on destruction.
KHook::Action ToKHookAction(HookAction action)
Subscription ToSubscription(std::unique_ptr< Hook > hook)
KHook::Return< Ret > ToKHook(HookResult< Ret > result)
void Info(std::format_string< Args... > fmt, Args &&... args)
Result< Subscription > HookVirtual(std::string_view name, const VirtualFn< Ret(Object *, Args...)> &function, Before &&before, After &&after=nullptr)
Hook a gamedata-bound virtual function on objects sharing its class vtable.
Ret CallOriginal(Ret(Iface::*method)(Args...), Iface *instance, Passed &&... args)
Result< Subscription > HookFunction(std::string_view name, const Fn< Ret(Object *, Args...)> &function, Before &&before, After &&after=nullptr)
Hook a signature-bound function at its entry.
static std::string ReadFile(const std::filesystem::path &path)
@ Replace
Let it run, but return this value instead of its own.
@ Block
Skip it entirely and return this value.
Subscription HookInterface(Ret(Iface::*method)(Args...), Iface *instance, Before &&before, After &&after=nullptr)
Hook one virtual method of an engine interface for a subscription's lifetime.
static InstalledScan Installed()
std::expected< T, Error > Result
static Error Unsupported(std::string detail)