Raised This Month: $46 Target: $400

AngelScript Mod Loader

Post New Thread Reply   
Thread Tools Display Modes
Author Message
Senior Member
Join Date: Sep 2015
Old 11-23-2016 , 13:27   AngelScript Mod Loader
Reply With Quote #1

For the past few days i've been working on a Metamod plugin that uses Angelscript as its scripting language. It's called the AngelScript Mod Loader, or ASMod for short.

Essentially this plugin is intended to be AMX Mod, only with Angelscript as its scripting language. There are multiple reasons why Angelscript is a good choice for this.

For starters, Angelscript binds directly to C++ code, which makes it more efficient to use than a language like Pawn, which uses cells. That requires wrapper functions in order to communicate between scripts and the C++ code it's accessing.

Second, it's object oriented. Types in C++ can be exposed to scripts exactly as they are. For example, entvars_t can be exposed as a reference counted type with properties; array properties are exposed using property getters and setters to provide a uniform representation of its members.

This makes using types more efficient and less error prone, since you can't pass the wrong enum value to a "pev" function by mistake.

And last but not least: since Sven Co-op also uses it, there is the potential to connect the two together and use the same script engine.

Which is exactly what i've done.

Using a few function addresses from Sven Co-op's server library, i was able to retrieve its script engine pointer. I then used this to add new API features to it.

As a test, i added my SQL API to it. This API was already integrated into HLEnhanced, though there are still a few things i want to take care of before calling it finished.

I modified one of my plugins to test it:
[email protected] g_pConnection = null;

void PluginInit()
    g_Module.ScriptInfo.SetAuthor( "Solokiller" );
    g_Module.ScriptInfo.SetContactInfo( "www.twhl.info" );
    @g_pConnection = SQL::CreateMySQLConnectionWithDefaults();
    g_Game.AlertMessage( at_console, "SQL connection created: %1\n", g_pConnection !is null ? "yes" : "no" );
    g_pConnection.Query( "SELECT * FROM Test", MySQLQueryCompleted );

void MySQLQueryCompleted( [email protected] pQuery )
    g_Game.AlertMessage( at_console, "MySQL Query completed\n" );
This script compiles and runs just fine in Sven Co-op's plugin environment. My SQL code is accessed and ran as if it were a part of Sven Co-op's own code.

Memory allocation occurs on Sven Co-op's server library heap thanks to a few other functions that i retrieved from the library. This allows me to seamlessly integrate new features and make them function as though Sven Co-op's own code is responsible for it. I even added a new string type that converts to their string type as needed, using these memory allocation functions to ensure that the right heap is used.

Once i've reworked some of my utility code and added some features that i want added to the SQL API, i'll be able to not only provide a completely asynchronous MySQL and SQLite API, but also a new filesystem interface that allows write access, access to engine data that was not exposed in SC's API, like model data, as well as the ability to hook any engine or game interface function and overriding them if you so desire. Essentially, you'll be able to do what you can do in AMX Mod.

The entire Metamod plugin, as well as all of the modules that provide new features are all available in the Github repository, which can be found here: https://github.com/SamVanheer/ASMod

I've only just gotten the essentials to work, so expect a lot of changes, but it's already off to a good start.
This plugin will eventually be able to function on its own as well, allowing you to use Angelscript in any GoldSource game that supports Metamod. Because of the module based approach to adding API functionality, individual games can have support for them implemented without any interference for other games, and shared code can be easily added.

In addition, i'll probably be adding Steamworks access to Metamod-P as well, which will come with new functions to hook into. For instance, a function that gets called when a player has been validated by Steam, which is something that has been requested by plugin authors to better handle the issue of players' Steam ID not being valid right away.

I'll be continuing work on this for a bit more to make it work standalone as well, which will also provide even more power to the Sven Co-op interop feature since it will let you write plugins that can access map script only features directly.
Things like custom entities are currently non-functional in plugins because (among other things) the access mask for those API features is set to map scripts only. All i have to do is provide the plugin module with an access mask that covers that mask and it will be able to access it.

All that said, this is just the beginning of this project. There is a lot to do before all of this becomes possible and stable, and efficiency is an important factor as well. And all of the new features would be useless without documentation to go with it. Fortunately i'll be able to provide that documentation on the wiki pages for the relevant projects.

Do keep in mind that it's a lot of work to build such an API, and when it comes to Sven Co-op the ability to access its data is dependent on them not changing how the implementation is structured.

If they choose to change it to break this plugin, then there is nothing i can do about it. However, considering how few updates their API has received in the past few months, i would strongly recommend supporting this plugin. I have provided an interface that games can export to more directly support this plugin: https://github.com/SamVanheer/ASMod/...SEnvironment.h
All you have to do is implement it, and use interface.h's EXPOSE_SINGLE_INTERFACE macro to export the class so it can be retrieved by the plugin. It's trivially simple to implement:
class CASGameEnvironment final : public IASEnvironment
    asIScriptEngine* GetScriptEngine() override final { return gASManager()->GetScriptEngine(); }

    asALLOCFUNC_t GetAllocFunc() override final { return ::operator new; }

    asFREEFUNC_t GetFreeFunc() override final { return ::operator delete; }

    asALLOCFUNC_t GetArrayAllocFunc() override final { return ::operator new[]; }

    asFREEFUNC_t GetArrayFreeFunc() override final { return ::operator delete[]; }

    IASLogger* GetLogger() override final { return nullptr; }

This is specific to Sven Co-op, hence the gASManager reference. The logger is completely optional; it's there so games can control the logging behavior of the plugin and integrate it with their own logging features if needed. If it's null, it creates its own logger instead.

The interface might change in the future, but i doubt it's going to happen since this is all that's really needed to make an implementation work. If it does, and there is no way to make all users upgrade, i'll take advantage of CreateInterface's versioning feature and just make it fall back to loading this older version, assuming the changes aren't required to make it work properly. It's still in development, so i'd suggest waiting a bit.

I'd like to hear about people's opinions, any suggestions or feedback, ideas, etc. If you think i'm evil for doing this considering past events, you can say that too
Solokiller is offline
AlliedModders Donor
Join Date: May 2013
Location: Serbia
Old 11-23-2016 , 13:57   Re: AngelScript Mod Loader
Reply With Quote #2

Originally Posted by Solokiller View Post
I'd like to hear about people's opinions, any suggestions or feedback, ideas, etc.
I luv u.

Originally Posted by Solokiller View Post
If you think i'm evil for doing this considering past events, you can say that too
Quite evil.

Anyway, shouldn't this be in Module Coding?
Also from the moment they released SC5.0, I had an idea similar to this. Though, my vision was to make AS plugins operate together with AMXX plugins by allowing them to share natives/forwards (it would've been an AMXX module, not Metamod plugin). So you could choose if you wanted to write a plugin using AS or Pawn. Not sure how possible is that - probably is but with some ugly hacking.

Last edited by KliPPy; 11-23-2016 at 14:02.
KliPPy is offline
Senior Member
Join Date: Sep 2015
Old 11-23-2016 , 14:15   Re: AngelScript Mod Loader
Reply With Quote #3

Pawn declarations don't really work with Angelscript. Angelscript is very similar to C++, but API functionality is provided automatically, not in a header that has to be included. It is possible to provide the same natives and forwards, but due to the cell based approach any C++ code will need to be wrapped by Pawn's cell functions, whereas Angelscript can access it directly.
Angelscript's C++ code is just that, C++ code. Angelscript scripts pass in data types that were registered by the program, and the native type is used by C++ code to communicate.

Then there's the need to map IDs in Pawn to the objects they represent. If the ID isn't just the memory address then you'll need lookup tables, and since Angelscript uses reference counting for reference types it'll complicate matters.

Functionality wise i can provide natives and forwards as long as it only concerns the engine API and new Metamod features (Steamworks API callbacks, etc). Game specific code is off limits because i'd have to get the addresses for every function every time they release an update, and the functions would need to be unoptimized so function arguments are passed on the stack. Otherwise you end up calling a function that is optimized to pass arguments through registers.

Once you factor in cross-platform support it really gets nuts. I know that there are AMX plugins that do this (Orpheus?) so it is possible, but beyond what i can provide, at least on short notice. I'm sure the functionality provided by Orpheus can be used by this too though, but it'll take some doing.
Solokiller is offline
AlliedModders Donor
Join Date: May 2013
Location: Serbia
Old 11-23-2016 , 14:19   Re: AngelScript Mod Loader
Reply With Quote #4

I knew most of that, that's why I never wrote it probably. :p

Anyway, here's an off-topic question for you: how to be productive and not lazy? I can hardly get myself to write anything outside my job, like modules for example. I need your brain.

Last edited by KliPPy; 11-23-2016 at 14:19.
KliPPy is offline
Senior Member
Join Date: Sep 2015
Old 11-23-2016 , 14:26   Re: AngelScript Mod Loader
Reply With Quote #5

Well most of this is stuff that i spent months thinking about before actually doing it. When you've already figured it all out you just need to write everything down. Aside from getting the function addresses pretty much everything i've done is stuff that i already knew how to do, so it was just a matter of getting it all out there.

I've mentioned before that there was a way to get the script engine, and i've spent some time looking into Metamod before (the CMake port was part of this). And i have quite a bit of time right now, little school work to do but that's because i'm absolutely terrible at anything that's not programming
All this skill has to cost something, and that something is not being very good at my other tasks.

It does help to make things trivial of course, CMake makes programming a lot easier because you can share code so much more. It's cross-platform, supports multiple versions of the same build tools, so i've saved myself a lot of time. Once i get the deployment stuff set up i don't even have to package the files anymore, just let the script do it for me.

Last edited by Solokiller; 11-23-2016 at 14:27.
Solokiller is offline
Senior Member
Join Date: Aug 2012
Location: Russia
Old 11-24-2016 , 05:20   Re: AngelScript Mod Loader
Reply With Quote #6

What about rehlds, regamedll support? They have own API for modules.
Mistrick is offline
Senior Member
Join Date: Sep 2015
Old 11-24-2016 , 07:01   Re: AngelScript Mod Loader
Reply With Quote #7

If these files contain the API setup: https://github.com/s1lentq/reapi/tre...reapi/src/mods
Then adding ReAPI support should be relatively simple. I'm already using CreateInterface for my API access code, so all i need to do is pass the game and engine's CreateInterface functions (if they have one), and add a module that exposes them.
Adding hooking code is probably a little more difficult, but it seems that it already provides the code for that, so i'll have to see about that.

I've never worked with ReAPI stuff so it might be best left for somebody else, i'll provide everything that's needed to make it work.
Solokiller is offline
[email protected]
Veteran Member
Join Date: Jan 2010
Location: Russia, Ivanovo
Old 11-24-2016 , 08:08   Re: AngelScript Mod Loader
Reply With Quote #8

ReAPI is only ReHLDS/ReGameDLL API wrapper for AMXX.
PRoSToTeM@ is offline
Send a message via ICQ to PRoSToTeM@ Send a message via Skype™ to PRoSToTeM@
Senior Member
Join Date: Sep 2015
Old 11-24-2016 , 08:16   Re: AngelScript Mod Loader
Reply With Quote #9

I figured as much, i was using it to refer to both the engine and game APIs.

Last edited by Solokiller; 11-24-2016 at 08:16.
Solokiller is offline
Senior Member
Join Date: Sep 2015
Old 11-25-2016 , 07:30   Re: AngelScript Mod Loader
Reply With Quote #10

I've implemented a FileSystem module. This is based on the one i wrote for Sven Co-op, but i've reworked pretty much the entire thing. I fixed a few bugs and simplified some code. I had to remove the SteamPipe filesystem from it because i don't have access to that set up yet.
I'm wondering whether i should hardcode it to only work with that, or to use the one i wrote for the prototype engine to replace it if this plugin is being used for a non-Steam engine.

Currently all directories are hardcoded, but i'll be making it read from a config file so server operators can control which directories scripts can access.
You can find the current list of hardcoded directories here: https://github.com/SamVanheer/ASMod/...Module.cpp#L69

Once i can get a release set up you'll be able to get this information using the asmod_fs_dumpfilesystem console command, which writes that information to a file.

Accessible in Sven Co-op by prepending FS:: to all types, and replacing g_FileSystem with FileSystem:
    FS::[email protected] pFile = FileSystem.OpenFile( "scripts/plugins/temp/file.txt", FS::OpenFile::WRITE );
    g_Game.AlertMessage( at_console, "Opened file: %1\n", pFile !is null );
    if( pFile !is null )
        pFile.Write( "Hello World!\n" );
I think these were the 2 most requested features, so that's persistent data storage done. I also had a request to access model data, but that'll have to wait until i've made some changes to interfaces and until i can get a release set up so people can download and install this.
Solokiller is offline

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

All times are GMT -4. The time now is 10:10.

Powered by vBulletin®
Copyright ©2000 - 2020, vBulletin Solutions, Inc.
Theme made by Freecode