Raised This Month: $82 Target: $400

Metamod-P with CMake

Post New Thread Reply   
Thread Tools Display Modes
Author Message
Senior Member
Join Date: Sep 2015
Old 11-20-2016 , 07:13   Metamod-P with CMake
Reply With Quote #1

I ported Metamod-P to CMake, you can find the repository here: https://github.com/SamVanheer/Metamod-P-CMake

Metamod-P's repository includes Metamod-P itself as well as a few plugins, which didn't have Visual Studio projects. With CMake this should no longer be a problem.

I also fixed a bunch of compiler warnings, nothing that affects code execution but it makes things easier to work with. I also converted some macros to template functions to make them type safe. (It was necessary because the compiler was issuing constant expression in conditional statement warnings about the code in the macros)

You can find the changelog here: https://github.com/SamVanheer/Metamo...wiki/Changelog

I think there are a few things that can be improved in it, for instance converting path separators to the current OS default will make writing plugins.ini entries a bit easier.

I'm pretty sure it's all good to go, but if there's anything i missed, feel free to let me know, i'm always interested in feedback

I'll make a branch for Sven Co-op too so it's all in one place.

EDIT: Sven Co-op branch has been made and updated with required changes. In addition to the changes that i made last time, all other areas that deal with engine and game functions have also been updated, the default plugins have also been updated. I've also updated the default Sven Co-op server library name to match the new name used since 5.0.

I've tested it on both Windows and Linux, both run (Linux client is broken but the dedicated server works) and the stub plugin loads successfully on both. On Windows AMX Mod works to the extent that it loads and runs idly without crashing, but i can't know for sure if it will work.

Last edited by Solokiller; 11-20-2016 at 08:23.
Solokiller is offline
Veteran Member
Join Date: May 2016
Old 11-20-2016 , 10:15   Re: Metamod-P with CMake
Reply With Quote #2

Didn't understand you
You mean you have modified metamad-p to make it better ?
['O|s|G'] | Death Wins a.k.a Ish Chhabra was here
ish12321 is offline
Senior Member
Join Date: Sep 2015
Old 11-20-2016 , 17:11   Re: Metamod-P with CMake
Reply With Quote #3

It's better in that it's easier to provide new releases. I've just finished setting up an automatic build system for Windows and Linux binaries, so whenever i push a new version it automatically builds debug, optimized and optimized+meta_debug disabled versions of Metamod-P, stub_plugin, trace_plugin and wdmisc_plugin.

I'm currently setting up the Sven Co-op fork to do the same.

EDIT: Both are set up now.


Both should be stable, but it requires testing on a server running Metamod plugins (e.g. AMX Mod) with players to activate the plugins' behavior.

Last edited by Solokiller; 11-20-2016 at 17:45.
Solokiller is offline
Senior Member
Join Date: Feb 2015
Old 11-21-2016 , 04:54   Re: Metamod-P with CMake
Reply With Quote #4

Do i sense a ReMetamod coming?
safetymoose is offline
Senior Member
Join Date: Sep 2015
Old 11-21-2016 , 05:04   Re: Metamod-P with CMake
Reply With Quote #5

There isn't much left to do with Metamod, but i can think of a few improvements to make.
Solokiller is offline
Senior Member
Join Date: Sep 2015
Old 11-30-2016 , 14:27   Re: Metamod-P with CMake
Reply With Quote #6

I've made a few updates to Metamod:

* Metamod now defines and exports the CreateInterface function and forwards calls to the game library if it does not handle them itself. This lets you intercept any C++ interfaces that the engine might try to create (none in Half-Life so far, but perhaps some day...)

* The engine handle, base filename and architecture (on Linux) are now identified so they can be used. The base filename is the library name without the path, extension or arch suffix. For Windows this is just the filename, for Linux dedicated servers this is "engine". The architecture is reported as "Windows", "Linux" (hw.so) or "i<arch>".
For example:
Adding: valve/addons/metamod/dlls/metamod.so
Engine library name: engine; arch: i486

* The CreateInterface functions for Metamod, the server, and the engine are all passed to plugins using a new function called Meta_Factories: https://github.com/SamVanheer/Metamo...a_api.cpp#L131
This function gets a structure containing those factories, as well as a factory that can instantiate either Metamod or game interfaces. This is the factory used by the game.

In addition, any factories that may be added in the future can be added transparently to the list. As long as plugins make sure to enumerate the list of extra factories they'll be able to get interfaces from them. I will probably copy the Metamod and game factories into that list so you don't need to write special case code.

* I've added the Steamworks library and linked it to Metamod. It will now provide an interface called IMetaSteamworks that exports methods needed to set up Steamworks access in a plugin. Plugins need only add a source file that sets up the API for them and call Steamworks_InitLibrary in Meta_Factories to set up their local API instance.
Steamworks support is only partially finished, so you can't add callbacks yet. That shouldn't be too difficult to get set up though.
What's available so far will let any Metamod plugin access Steamworks v1.20 (included in the Source SDK 2013 when it was first released) and use its interfaces. You can query for various things, like the current app ID (useful for identifying the game, though dedicated servers will likely get 90), the server's Steam ID, etc.

Access to this API is currently in the alpha stage due to required functions not being available to plugins yet. I might have to rework it to allow Metamod to intercept certain interfaces, because some of them seem to be exploitable. Some of them seem to allow the modification of a user's name, access to their friends list, etc. For listen servers this could be dangerous, so all Metamod plugins you run should be open source and audited.

I'll also be providing helper functions/types to convert Steam IDs to their Steam2 string equivalent, which is what pfnGetPlayerAuthId returns. That should deal with any interoperability issues.

Once that's done any Metamod plugin should be able to access Steamworks with minimal effort.

Last edited by Solokiller; 11-30-2016 at 14:52.
Solokiller is offline
Senior Member
Join Date: Sep 2015
Old 12-01-2016 , 11:12   Re: Metamod-P with CMake
Reply With Quote #7

I've pretty much finished the Steamworks integration. I had to make plugins link with it since some of the API features only work properly if it's still able to call into it when the plugin unloads, but i don't think that'll be a big issue.

I've added a class that can convert between auth IDs, Steam3 IDs and Steam2 IDs, so you can convert between them at will with close to 100% accuracy. Steam2 IDs are missing the universe property that Steam3 IDs have, which is why it isn't a perfect conversion.
If you catch the game server ClientApprove and ClientDeny callbacks you can look up the client's Steam2 auth ID and match it up, so you can keep a lookup table matching auth IDs to their Steam3 equivalent.

As long as you can't have 2 clients where their Steam3 IDs are identical for all components except the universe, it should never fail.
From what i know of Steam IDs, the universe defines what kind of Steam environment you're in, so you should never be able to connect to the same server with 2 Steam IDs that have only differing universes.

From what i can tell, all Steamworks features are now available, provided the feature is either always enabled or enabled for the game/mod you're running with. The User Generated Content interface is unavailable in this version of the Steamworks library, so there is no way to access that even if it were enabled.

One important thing to note about accessing the server API (ISteamGameServer): the interface instance is only created when the server actually starts the Steam connection, which occurs right after the first map has loaded and pfnServerActivate has been called. To work around this hard-to-catch event, i've added a listener interface that gets called when this occurs, and when the server shuts down so you can easily manage your Steamworks API access.

The stub_plugin example has this all set up, and will automatically initialize its local context when needed.

Here's a simple example showing how you can add a callback for the game server client authentication approved callback:

#include "plugin/SteamworksAPI.h"
class CAPICallback

    STEAM_GAMESERVER_CALLBACK( CAPICallback, OnGSApprove, GSClientApprove_t, m_CallbackGSApprove );

    : m_CallbackGSApprove( this, &CAPICallback::OnGSApprove )

void CAPICallback::OnGSApprove( GSClientApprove_t* pResult )
    CSteam2IDString authID( pResult->m_SteamID, false );

    LOG_MESSAGE( PLID, "Client approved: %llu, %s", pResult->m_SteamID.ConvertToUint64(), authID.GetString() );

CAPICallback g_Callbacks;
Callbacks can be registered at any time, though i suspect it's normally supposed to happen after a SteamAPI_Init(Safe) call, but because plugins are loaded after Metamod has done that, you can just use static constructors to do this at will. You can register multiple callback functions for the same event, just like Metamod does with multiple plugins handling the same callback. The callback system functions much like Metamod's callback system does, except it doesn't let you do the ignore/supercede/etc part.

This callback is invoked if a client successfully authenticates with Steam, and usually occurs a few seconds after the client has joined the game. The first value that is printed is the 64 bit Steam ID value, the second is the Steam2 auth ID used by GoldSource.

Note the boolean argument for the CSteam2IDString constructor. This indicates whether this is a lan game. If it's a lan game, it sets the auth ID to STEAM_ID_LAN; if it's not a lan game and the Steam ID is 0 it sets the auth ID to STEAM_ID_PENDING. Otherwise, the auth ID is formatted as you'd expect.

I've experienced no issues using this on Windows, but on Linux the callback isn't invoked for either the engine or the plugin. This was already the case before i started integrating Steamworks, so it may have to do with running Linux in a virtual machine. I've also noticed Metamod errors with engine functions not being found on Linux, so this could be caused by a larger issue, i'll have to investigate that.

Last edited by Solokiller; 12-01-2016 at 12:00.
Solokiller is offline
Senior Member
Join Date: Sep 2015
Old 12-04-2016 , 05:58   Re: Metamod-P with CMake
Reply With Quote #8

I've corrected the problems with engine functions not being found. Turns out Metamod tries to validate engine function pointers using addresses it gets from very specific debug information. It derives this information from the name of the engine library. Only problem was it didn't know about the Linux client engine (hw.so) so listen servers never worked. I've now added support for this, so you can run Metamod on Linux listen servers.

It still isn't invoking the callback, but i figure that's the VM i'm using. Unless native Linux servers also aren't getting those i don't think there's any reason for concern there.

I've updated the changelog: https://github.com/SamVanheer/Metamo...wiki/Changelog
Solokiller is offline
Senior Member
Join Date: Sep 2015
Old 12-08-2016 , 13:31   Re: Metamod-P with CMake
Reply With Quote #9

I've reworked Steamworks support a bit. A number of interfaces are only available when running as a client application, so servers can't use them unless there's a Steam client instance active. Dedicated servers hosted standalone using SteamCMD would fail to load Metamod.

You can access a few interfaces, i'll show some useful applications of them:

g_pSteamServerAPI->SteamGameServer()->SetMapName( "Cool map name" );
g_pSteamServerAPI->SteamGameServer()->SetGameTags( "tag1;tag2" );
g_pSteamServerAPI->SteamGameServer()->GetSteamID(); //Server Steam ID
g_pSteamServerAPI->SteamGameServer()->GetPublicIP(); //Server's public IP address. May be 0 if unknown.
g_pSteamServerAPI->SteamGameServerUtils()->GetAppID(); //Current game App ID, can be used to identify current game.
You can also use Steam's P2P networking interface, maybe you can send data to servers that way?

There's also the HTTP interface, but the engine is already using that to handle FastDL so you'll likely interfere with that system by using it.

There's a development release on Github if anyone wants to try it.
Solokiller is offline
[email protected]
Veteran Member
Join Date: Jan 2010
Location: Russia, Ivanovo
Old 12-09-2016 , 06:59   Re: Metamod-P with CMake
Reply With Quote #10

Originally Posted by Solokiller View Post
when running as a client application
You mean listen server or what?
Originally Posted by Solokiller View Post
There's also the HTTP interface, but the engine is already using that to handle FastDL so you'll likely interfere with that system by using it.
But it is used only by the client engine.

Last edited by [email protected]; 12-09-2016 at 07:01.
PRoSToTeM@ is offline
Send a message via ICQ to PRoSToTeM@ Send a message via Skype™ to PRoSToTeM@

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 06:19.

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