Server plugins

Server plugins are C++ code libraries that modify the behaviour of dedicated servers. They are used to provide everything from maintenance tools to additional gametypes.
== Installing ==
Source automatically loads plugins defined in files matching <game>/addons/*.vdf. 
== .vdf format ==
These files should be formatted like this:
 Plugin
 {
 	file		"<path to plugin>"
 }
The path is relative to the folder that gameinfo.txt resides (i.e., the mod base folder).
== Managing ==
The following console commands are provided:
* plugin_print (provides IDs for use with other commands)
* plugin_load
* plugin_unload
* plugin_pause (the engine stops sending callbacks to the plugin)
* plugin_unpause
* plugin_pause_all
* plugin_unpause_all
== Coding ==
:You can find a sample plugin project at src\utils\serverplugin_sample\. The Orange Box version is good for both Source 2007 and 2009.
Plugins work by exposing an object inheriting from IServerPluginCallbacks and IGameEventListener2 to the engine. Source will send function calls into the plugin at various times, hard-coded and or listened for, and the plugin can react to each of those events by running its own code. In some cases (e.g. player connection) changing the outcome of the original function is also possible.
The most important caveat is that you cannot access server classes. Each plugin is a discrete library that can only access the parts of the server that are exposed through Source's various interfaces. The likes of CBaseEntity are not available; entities are instead represented with edict_t. 
=== Compiling ===
; Windows
: Build with the Visual Studio project provided; see Compiling under VS2008 or Compiling under VS2010 for help with upgrading
; Linux
: Navigate to src/linux_sdk/, edit Makefile.plugin to include your files, and then execute make plugin.
:If you are compiling for Source 2009, you must change the names of some Valve libraries in Makefile and Makefile.vpcm: 
:* tier0_i486 > libtier0
:* vstdlib_i486 > libvstdlib
:* steam_api_i486 > libsteam_api 
: Use ldd -d <plugin.so> to check for dependencies. It won't be able to find the libs; just worry about what they're called.
; Mac
: Not possible yet
To debug your plugin, you must launch the server with -allowdebug.
===Listening to Events===
The IGameEventManager2 (IGameEventManager was used previously) interface allows a plugin to listen to game events. Game events are fired by a Mod when things of interest happen, like a player dying or the bomb being planted. IGameEventManager2::AddListener should be called to subscribe to particular game events. It must be called for each event that your listener wishes to be aware of. FireGameEvent is then called in your plugin when an one of the listened for events happen. The data contained in each event is described by event configuration files, in particular:
* hl2/resource/serverevents.res
* hl2/resource/GameEvents.res
* <mod dir>/resource/ModEvents.res
===Creating ConVars and Commands===
ConVars let you specify variables that users can use to configure the behavior of your plugin. ConCommands allow the creation of commands that your plugin provides. Creating both is easy and self contained, the code snippet below creates a new command empty_version and a new variable plugin_empty. These commands can be run from the server or client, you should use the index provided by SetCommandClient to determine the source of the command.
CON_COMMAND( empty_version, "prints the version of the empty plugin" )
{
 Msg( "Version:1.0.0.0\n" );
}
static ConVar empty_cvar("plugin_empty", "0", 0, "Example plugin cvar");
=== Other tricks ===
Get player entities:
static CGlobalVars *gpGlobals;
static IVEngineServer *engine;
CON_COMMAND( list_players, "Prints the name of each connected player" )
{
	for (int i=1;i<gpGlobals->maxClients;i++) // EntIndex 0 is worldspawn, after which come the players
	{
		// n.b. this only works if the player is active; players still connecting won't show up
		IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo(engine->PEntityOfEntIndex(i));
		if (playerinfo)
		{
			Msg(playerinfo->GetName());
			Msg("\n");
		}
	}
}
Add and remove a server tag:
#include <string>
void AddTag(char* MyTag)
{
	static ConVar* sv_tags = cvar->FindVar("sv_tags");
	std::string tag_string;
	tag_string.assign(sv_tags->GetString());	
	if (tag_string.find(MyTag) == -1)
	{
		if (tag_string.length() && tag_string.at(tag_string.length()) != ',')
			tag_string.append(",");
		tag_string.append(MyTag);
		sv_tags->SetValue(tag_string.c_str());
	}
}
void RemoveTag(char* MyTag)
{
	static ConVar* sv_tags = cvar->FindVar("sv_tags");
	std::string tag_string;
	tag_string.assign(sv_tags->GetString());	
	size_t start = tag_string.find(MyTag);
	if (start != -1)
	{
		tag_string.erase( start, tag_string.find(start,',') );
		sv_tags->SetValue(tag_string.c_str());
	}
}
== See also ==
* Client plugins
* Left 4 Dead Plugins
* Orange Box server plugins
* Querying ConVars from Server Plugins
Category:Plugins
Category:Dedicated Server
Category:Plain text files
Category:Plain text formats