Counter-Strike Sourcemodding: What is SourceHook?

Mooshua

Vine-Ripened, non-GMO, and USDA Certified Organic.
Tech
SourceHook turns 19 next month. I thought you all might appreciate a little look into this piece of Source engine history.

SourceHook is the powerful core of Metamod, the plugin manager at the heart of Sourcemod and all Source 2 modding. SourceHook was originally developed in 2005-2006 by the core authors of SourceMod to enable rapid development on the new Half-Life 2 engine, and has since been a staple of all Source engine modding. Every server you've played on has probably relied on SourceHook to some extent, but it unfortunately remains a forgotten, if not incredibly elegant, artifact of modding history.

The Original Metamod


When GoldSrc was published, modders started creating what we now know as GameDLL mods. A GameDLL mod would trick the engine into loading the mod instead of the real game, allowing the mod to sit between the engine and the real game. The mod could then instrument or hook the game's invocation of the engine (and vice versa). However, the engine could only be tricked into loading one plugin, causing conflicts and compatibility issues when multiple plugins needed to be used. This led to the development of the original Metamod, a simple plugin that loaded other plugins and allowed them to each cooperatively invade the engine's privacy.


Metamod.drawio.png


Metamod was slow, but it worked. The simple architecture of the GoldSrc engine meant that it didn't need to be very complex, and the original Metamod became a standard for plugin development. Unfortunately, valve then decided to f**k it all up with Source.

The Source Engine


The new Source engine threw out the simple design of the engine-game communication, and adopted the interface pattern; a system where each Object (or class instance) started with a pointer to a Virtual Table. Each virtual table contained a list of functions that could be invoked if you knew the number of the method (or offset) you wanted to invoke.


VirtualTable.drawio.png


Virtual Tables allowed valve to build a vastly more complicated engine and build more features for their games. However, it came at the expense of modders: while Valve was extraordinarily kind in publishing the definitions for each virtual table at the game's launch, the complexity of the new engine meant that it would be virtually impossible to sit between the entire engine; there was simply too much ground to cover and too many features to replicate. On top of that, the engine began changing, fast, to accomodate new features, breaking compatibility and leaving modders fuming. In 2005, BAILOPAN wrote:

[Valve] often change interface versions for their own first-party mods without releasing the changes. This was originally the case with PlayerInfoManager, which was version 002 on CS:S and 001 on HL2MP. Worse yet is the DoD:S problem, where Valve is now using two different versions concurrently, and Valve hasn’t even posted the interface changes publically. Therefore, people must either assume that the 003->004 version jump maintains backward compatibility (which a version increase should always do, but the actual design doesn’t implicate, as you must know about the future version in advance), or that it has changed and you can’t support it. Either way, you’ve lost both proper backward compatibility with future versions, and you’ve lost mod-independent support, as Valve has stated that their interface design doesn’t always have to be public, but worse, they can change it at any time to suit their first-party mods. It’s ugly. It’s a mess. In short, it’s the HL2SDK

Additionally, without sitting in between the engine and the game, it would be impossible to ensure plugins didn't interfere with each other when they began instrumenting the game. By March 2005, modders were done dealing with Valve's massive new interface, and decided to take things into their own hands with the development of Metamod: Source (henceforth called simply "Metamod").

Released in May 2005, Metamod: Source was put apart from the competition with it's unique solution to Valve's new interface. Instead of trying to sit between the entire engine and the game, Metamod stood between absolutely nothing at all. It did nothing. No instrumentation, no modifications. It just sat there and watched.

The real power of Metamod came from the target of this article, SourceHook. When plugins were loaded, SourceHook would begin replacing the engine's Virtual Tables with SourceHook tables. SourceHook could then swap out individual methods with instrumentation for plugins, while keeping the rest of the virtual table as the original from the game. Since SourceHook kept track of all the changes it made, it allowed plugins to work alongside each other by preventing them from undoing the other's detours. And, since it only sat between the engine when plugins needed to listen in, it was fast.


SourceHook.drawio.png


Using SourceHook, Metamod didn't need to worry much about game compatibility anymore: as long as it was able to load and know some basic information about the game's state, it could run just fine. The engine could have massive changes to it's interface and Metamod could keep chugging along. (It's plugins, on the other hand...). This basic attribute allowed Metamod to be ported to Source 2 quickly, and was the essential boost that led to rapid expansion into the Counter-Strike 2 scene.

Due to SourceHook working on only individual methods, many plugins (like SourceMod!) didn't really need to know much about the objects it was hooking; all they had to do was tell SourceHook which method it needed to hook and what arguments the hooked method expected to be given. Plugins began needing less work to maintain, and reverse engineering efforts could be focused on new features rather than ensuring engine-to-game compatibility. To this day, you'll find the HL2SDKs riddled with "Unknown" methods: undocumented by Valve and a mystery to reverse engineers, but completely irrelevant thanks to SourceHook.


SourceHook Today


Since 2005, SourceHook has undergone several major updates and is compatible with all major C++ calling conventions, playing nice with the quirks of GCC and MSVC. Even today, SourceHook is the heart of all Source-engine development, from Sourcemod's vibrant plugin scene to newer developments like CS2Fixes and Counter-Strike Sharp. SourceHook's simple, elegant, and impressively bulletproof codebase accelerates our development and reduces iteration time.

Despite being a largely independent project from Metamod, SourceHook never really left the Source community. With a large amount of games forgoing interface-based architectures, many modders turned to static detours and real-time disassemblers to make their modifications. Virtual Hooking has largely become an obsolete instrument of the modding scene.

Nonetheless, we look forward to seeing SourceHook's charming little macros in our expansion into the Source 2 engine. Here's to another two decades, SourceHook. Happy early birthday :)

Correction: I initially wrote “SourceHook turns 20”. This is wrong and I apologize to everyone impacted by this terrible and preventable mistake.
 
Last edited:

Latest posts

Back
Top