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:
Code:
#include "plugin/SteamworksAPI.h"
class CAPICallback
{
public:
CAPICallback();
private:
STEAM_GAMESERVER_CALLBACK( CAPICallback, OnGSApprove, GSClientApprove_t, m_CallbackGSApprove );
};
CAPICallback::CAPICallback()
: 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.