ConVars (cvars) in SourceMod

Today’s article is mostly a wiki addition: ConVars (SourceMod Scripting).

The major difference between SourceMod’s cvar API and AMX Mod X’s is how cvars are addressed. AMX Mod X references cvars by name, a string. SourceMod’s cvar API references by a Handle, which contains the ConVar pointer.

AMX Mod X’s failure to use the HL1 cvar_t pointer is nothing short of horrendous. The only benefit is that it makes coding much easier for newcomers. Unfortunately, it’s a huge performance issue. There are hundreds of cvars, and doing named lookups for every cvar operation is extremely painful, especially if the same cvar is used over and over again.

Even more concerning, it took the AMX Mod X developers (me included) a long time to notice this. Only later in the 1.x branch were “pcvar” natives introduced. These natives dealt with direct cvar_t pointers, and used the engine call SET_CVAR_DIRECT to make changes. One must wonder why HL1 even had SET_CVAR_FLOAT and SET_CVAR_STRING, as it basically encourages using much slower code.

While many people still use AMX Mod X’s name based lookup, “pcvar” usage is encouraged. Of course with SourceMod, it is the only option.

SourceMod maintains similarity with AMX Mod X’s “pcvar” API by using one Handle for every named cvar. If two plugins create or find the same cvar, they will both receive the same Handle. Thus, no plugin owns any cvars, and cvars are not removed until SourceMod unloads. This has a few benefits:

  • You can directly compare cvar Handles. For example, instead of doing a strcmp() call, you can do if (hndl1 == hndl2)
  • If a plugin unloads, the cvar will stick around, so any settings will still be set if the plugin reloads or refreshes.
  • Plugins don’t have to call CloseHandle() simply for finding a ConVar

The other major difference is that HL2 engine passes ConVar changes through a callback. Thus, you can detect changes without making a secondary console command. This was not possible in HL1. Although you could hook SET_CVAR_FLOAT, it was not virtual, and thus internal or plugin usage of it would not be caught. Also, the change callbacks are per-ConVar; HL1′s is global, and thus a bit less optimized.

3 Responses to “ConVars (cvars) in SourceMod”

  1. Zenith says:

    Wow wish AMXX had handles. I know this may seem like a stupid question, and I pretty much already know the answer to it: How hard would it be to port SourceMod’s scripting system (SourcePawn) into AMXX (exclude backwards compatibility for a moment, this is just out of curiosity).

  2. BAILOPAN says:

    It’d be a huge amount of work since the API is very, very different (C procedural versus C++ objects). Even if we made wrappers from the old API to the new, it’d be a large undertaking, and we’d have to completely strip out 64bit support. Without wrappers, old code simply wouldn’t compile, much less be backwards compatible.

    We thought about it for about half a second and then realized it wasn’t worth it.

  3. Zenith says:

    Figured that. Thanks for your answer.

Leave a Reply

You must be logged in to post a comment.