MetaEng – Part I

So how does SourceMod handle different scripting languages anyway? Doesn’t that seem rather crazy? Here’s a look into how exactly this was achieved.

In the world of scripting, plugins provide one, and only one functionality – callbacks. They have entrypoints which hook or modify functionality in a parent application. These entry points are known as “events”, “callbacks”, or “public functions”. Much like an external C function, they can be looked up, by name, by the parent virtual machine/bytecode interpreter.

Therefore, MetaEng’s task is fairly simple, right? All it has to do is create a layer for finding a named function in an object and call that function with basic data types. For example,

IScript *script = Plugin->GetPluginScript();   //get MetaEng Context
   IForward *f = g_ForwardMngr.SingleForward(script, "plugin_init", 0);

And this is exactly how MetaEng works. There are three important pieces to the MetaEng model:

  • Forwards – Execution interface for scripts.
  • Scripts – Interface for very basic and generic scripting functions.
  • MetaEngines – Implements a specific Script type (such as C++, AMX, or JavaScript).

Unfortunately, that’s just the interface side of things. It gets much more complicated when other topics are introduced – such as, how do we implement a universal method of passing parameters? How is the Forward layer implemented? How are plugins written in C/C++? What happens if a Script is destroyed/unloaded and Forwards are not removed?

And, perhaps most important, how do Natives work? Natives are functions native to the host application that can be called from a script. How does the host application, SourceMod, reconcile the fact that there is one set of natives written in C++, but many scripting languages?

I’ll answer these questions in the upcoming additions.

Leave a Reply

You must be logged in to post a comment.