-
Notifications
You must be signed in to change notification settings - Fork 101
Provide an alternative to SourceHook #223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Wouldn't it be better to put that dependency at a third_party subfolder instead of core? (You also seems to have multiple entries defined in .gitmodules) |
As things stand right now, yes it would make more sense to have it under But you made me realise |
Well amtl is also an am project, yet it's in the third_party subfolder, thus the question. Only if you mean you would transfer the code under the mm repo then I guess sure. |
cce4a9b
to
7c45817
Compare
For library dir location, I agree that I think either dropping it in the root or in a third_party dir is fine. I don't have a strong opinion of which specifically |
199215b
to
ffedcab
Compare
383e92d
to
6fd40ab
Compare
cec6816
to
10c3948
Compare
10c3948
to
28fb48b
Compare
What is the motivation behind this ?
With the advent of source 2 a lot of the modding rules have changed. Unlike source 1 games with sourcemod, there's currently no 'winner' over the modding space. Instead we have a ton of competing framework
CounterStrikeSharp
,CS2Fixes
,Swiftly
to name a few, each shipping with their own detour library. This of course, much like source 1 early days, is creating a ton of conflicts and unfortunately Metamod is currently not suited at handling those conflicts. While Source 1 modding primarily involved hooking virtual functions, this is not really the case anymore on Source 2. SourceHook needs to evolve into a proper detouring library.How does the new detour library work ?
Calling the new framework a detour library would be technically incorrect as it doesn't perform any actual detouring, that work is left to its backend
SafetyHook
. Instead it adds an extra layer of logic where each detour address is catalogued so that only one detour exists per address. However for the sake of public clarity I will refer to the whole as a detour library.Unlike
SourceHook
which relied on the consumer to implement the callback calling logic, the new framework is capable of handling that on its own. In order to achieve this the detour function is JIT'd and it makes a few assumptions such as :Note
All of that data is saved when the detour function is first invoked and then restored back before each detour callback invocation.
Inspired by
SourceHook
the callback logic is similar. There are PRE & POST callbacks, called before and after the detour'd function respectively. Each callback is given the option toTwo extra functions are invoked during the callback logic process. Because the framework is unaware which calling convention is being used by the original function it doesn't know how to store the return value if the original function is called, and it doesn't know how to perform the final return. That job is instead left to the detour consumers, a hook will be randomly selected to perform the original function call and store the value, and another hook will be randomly selected to perform the final return.
Helper functions are provided for the various callbacks :
Note
Each of those functions are thread-local. Meaning the value they return is for that thread only, this is a major difference with
SourceHook
since it enables hook callbacks to be thread-safe.Helper class
All of this was just the nitty gritty of how the new detouring library works internally, but much like
SourceHook
the consumers are not required to know all of this. Helper class are provided to use the detouring library in a straight forward manner.Each hook can be a global variable or member of a class, clean-up logic is handled automatically upon the hook's class destruction. There's also no macro-hell, everything is templated.
Callbacks are also simplified, you do not need to use a macro anymore you only need to return a valid
KHook::Return
struct and the hook override/supercede logic will be handled automatically.Why blow up
SourceHook
?Before answering, I would like to stress that
SourceHook
is a good framework in the context of why it was built i.e unifying virtual hooking. But as explained in the introduction, that's no longer the case for Source 2 modding and metamod must provide a unifying hooking interface not just limited to virtual functions.Upgrading
SourceHook
was not viable, a lot of its core concepts are tightly bound to virtual hooking so there is a ton of internal rework necessary and you would be essentially rewriting 90% of the callback logic, might as well start from scratch.However providing two detouring framework, or introducing some kind of backwards compatibility between the two is just going to enable the initial problem to continue. Metamod 2.0 is a thing, we are allowed to make such a huge breaking change and force everyone to abandon their own detour library flavor.
Another reason for blowing up
SourceHook
isHookmangen
, it's hard for me to describe what hookmangen is for. It creates the function that calls sourcehook callbacks on the fly, but it's abstracted away behind a ton ofSourceHook
specific flags. Why not just provide an assembly emitter to the consumer and let them implement the callbacks automatically, also why burden the consumer with the callback logic when it should have beenSourceHook
's job from the start. As of today, this portion ofSourceHook
has single handedly prevented Sourcemod's complete support of x86_64. But with the new framework, consumers will be able to JIT their own functions with whatever assembly instructions they desire.Naming/Licensing
Everything about that work is placeholder, I will transfer the whole repository to AM once this is ready for merge. I can't create repositories under AM and didn't want to bother anyone with something that might not see the light of day. Finally it's called
KHook
merely because of an inside joke (cook), we can rename to anything else if need be, it just made the code removal ofSourceHook
easier.