Creating A New Plugin
Introduction
This article will teach you how to set up a new Valve Server Plugin for Visual Studio. It may seem overwhelming at first, but it is actually very easy. The following is what you will be doing any time you want to create a new Valve Server Plugin.
Overview
Within your Source SDK 2013 folder, if you navigate to `mp/src/utils/`, you will notice a folder called `serverplugin_sample`, which contains a few files, mainly CPP files and a VPC file, that last file being very important. In order to keep this article simple, we will use this structure as a base for our new plugin.
Creating The Files
Create an identical copy of the `serverplugin_sample` folder including its contents and rename the folder to something that you would like. For all intents and purposes, we will call this folder `myfirstplugin_folder`.
Great, now we have our new folder with our files inside! Go inside your new folder. We currently have 2 CPP files, but for this article, one of them is unnecessary and can be removed. Delete `serverplugin_bot.cpp`. Now we are left with `serverplugin_empty.cpp` and `serverplugin_empty.vpc`. Rename both files to something you would like. Try to keep it consistent for organization purposes. For this article, we will use `myfirstplugin.cpp` and `myfirstplugin.vpc`.
Excellent, now we have set up our new folder and our new files!
The next step is to include our CPP file into the solution. To do that, we will use the Valve Project Creator. We will not need to use the executable, we will instead edit a few script files. Open `myfirstplugin.vpc` and you will see the following:
//-----------------------------------------------------------------------------
// SERVERPLUGIN_EMPTY.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE,$SRCDIR\game\server,$SRCDIR\game\shared"
$PreprocessorDefinitions "$BASE;serverplugin_emptyONLY;_MBCS"
}
$Linker
{
$AdditionalDependencies "$BASE odbc32.lib odbccp32.lib"
}
}
$Project "Serverplugin_empty"
{
$Folder "Source Files"
{
$File "serverplugin_bot.cpp"
$File "serverplugin_empty.cpp"
}
$Folder "Header Files"
{
$File "$SRCDIR\public\tier0\basetypes.h"
$File "$SRCDIR\public\Color.h"
$File "$SRCDIR\public\tier0\dbg.h"
$File "$SRCDIR\public\eiface.h"
$File "$SRCDIR\public\filesystem.h"
$File "$SRCDIR\public\tier0\icommandline.h"
$File "$SRCDIR\public\igameevents.h"
$File "$SRCDIR\public\tier1\interface.h"
$File "$SRCDIR\public\game\server\iplayerinfo.h"
$File "$SRCDIR\public\engine\iserverplugin.h"
$File "$SRCDIR\public\tier1\KeyValues.h"
$File "$SRCDIR\public\tier0\mem.h"
$File "$SRCDIR\public\tier0\memalloc.h"
$File "$SRCDIR\public\tier0\memdbgon.h"
$File "$SRCDIR\public\tier1\strtools.h"
$File "$SRCDIR\public\tier1\utlbuffer.h"
$File "$SRCDIR\public\tier1\utlmemory.h"
$File "$SRCDIR\public\tier1\utlvector.h"
$File "$SRCDIR\public\vstdlib\vstdlib.h"
}
$Folder "Link Libraries"
{
$Lib mathlib
$Lib tier2
}
}
}
This is the default serverplugin_empty's contents. For this article, we are going to keep everything and simply edit `serverplugin_empty` with the new plugin name `myfirstplugin` and remove `serverplugin_bot.cpp` since it is irrelevant in this case. You should then have something that looks like this:
//-----------------------------------------------------------------------------
// MYFIRSTPLUGIN.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$Macro SRCDIR "..\.."
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE,$SRCDIR\game\server,$SRCDIR\game\shared"
$PreprocessorDefinitions "$BASE;myfirstpluginONLY;_MBCS"
}
$Linker
{
$AdditionalDependencies "$BASE odbc32.lib odbccp32.lib"
}
}
$Project "Myfirstplugin"
{
$Folder "Source Files"
{
$File "myfirstplugin.cpp"
}
$Folder "Header Files"
{
$File "$SRCDIR\public\tier0\basetypes.h"
$File "$SRCDIR\public\Color.h"
$File "$SRCDIR\public\tier0\dbg.h"
$File "$SRCDIR\public\eiface.h"
$File "$SRCDIR\public\filesystem.h"
$File "$SRCDIR\public\tier0\icommandline.h"
$File "$SRCDIR\public\igameevents.h"
$File "$SRCDIR\public\tier1\interface.h"
$File "$SRCDIR\public\game\server\iplayerinfo.h"
$File "$SRCDIR\public\engine\iserverplugin.h"
$File "$SRCDIR\public\tier1\KeyValues.h"
$File "$SRCDIR\public\tier0\mem.h"
$File "$SRCDIR\public\tier0\memalloc.h"
$File "$SRCDIR\public\tier0\memdbgon.h"
$File "$SRCDIR\public\tier1\strtools.h"
$File "$SRCDIR\public\tier1\utlbuffer.h"
$File "$SRCDIR\public\tier1\utlmemory.h"
$File "$SRCDIR\public\tier1\utlvector.h"
$File "$SRCDIR\public\vstdlib\vstdlib.h"
}
$Folder "Link Libraries"
{
$Lib mathlib
$Lib tier2
}
}
}
Awesome! This should set us up for adding our new files in the solution, but we still need to edit a couple more VPC script files.
VPC Script Setup
Navigate to `mp\src\vpc_scripts` and open `groups.vgc`. Inside that file, you will notice different groups. Those are what you see in the solution explorer essentially based on what solution you wanted to generated (createdgameprojects.bat or createallprojects.bat). We will add our new project into the group `everything`. Simply create a new line and add `"myfirstplugin"`. You should have something that looks like this:
$Group "everything"
{
"captioncompiler"
"client"
"fgdlib"
"game_shader_dx9"
"glview"
"height2normal"
"mathlib"
"motionmapper"
"myfirstplugin"
"phonemeextractor"
"raytrace"
"qc_eyes"
"server"
"serverplugin_empty"
"tgadiff"
"tier1"
"vbsp"
"vgui_controls"
"vice"
"vrad_dll"
"vrad_launcher"
"vtf2tga"
"vtfdiff"
"vvis_dll"
"vvis_launcher"
}
Finally, in the same folder, open `projects.vgc`. We will add our project that we defined in `myfirstplugin.vpc`. Add the following somewhere under the project definitions:
$Project "myfirstplugin"
{
"utils\myfirstplugin\myfirstplugin.vpc" [$WIN32||$POSIX]
}
You should end up with something like this:
//-----------------------------------------------------------------------------
// PROJECTS.VGC
//
// Project Configurations for all Source(TM) Projects
//-----------------------------------------------------------------------------
/////////////////////////
// Project definitions //
/////////////////////////
$Project "captioncompiler"
{
"utils\captioncompiler\captioncompiler.vpc" [$WIN32]
}
$Project "client"
{
"game\client\client_hl2mp.vpc" [($WIN32||$POSIX) && $HL2MP]
}
$Project "fgdlib"
{
"fgdlib\fgdlib.vpc" [$WIN32]
}
$Project "myfirstplugin"
{
"utils\myfirstplugin\myfirstplugin.vpc" [$WIN32||$POSIX]
}
$Project "game_shader_dx9"
{
"materialsystem\stdshaders\game_shader_dx9_hl2mp.vpc" [$HL2MP]
}
$Project "glview"
{
"utils\glview\glview.vpc" [$WIN32]
}
$Project "height2normal"
{
"utils\height2normal\height2normal.vpc" [$WIN32]
}
$Project "server"
{
"game\server\server_hl2mp.vpc" [($WIN32||$POSIX) && $HL2MP]
}
$Project "mathlib"
{
"mathlib\mathlib.vpc" [$WINDOWS||$X360||$POSIX]
}
$Project "motionmapper"
{
"utils\motionmapper\motionmapper.vpc" [$WIN32]
}
$Project "phonemeextractor"
{
"utils\phonemeextractor\phonemeextractor.vpc" [$WIN32]
}
$Project "raytrace"
{
"raytrace\raytrace.vpc" [$WIN32||$X360||$POSIX]
}
$Project "qc_eyes"
{
"utils\qc_eyes\qc_eyes.vpc" [$WIN32]
}
$Project "serverplugin_empty"
{
"utils\serverplugin_sample\serverplugin_empty.vpc" [$WIN32||$POSIX]
}
$Project "tgadiff"
{
"utils\tgadiff\tgadiff.vpc" [$WIN32]
}
$Project "tier1"
{
"tier1\tier1.vpc" [$WINDOWS || $X360||$POSIX]
}
$Project "vbsp"
{
"utils\vbsp\vbsp.vpc" [$WIN32]
}
$Project "vgui_controls"
{
"vgui2\vgui_controls\vgui_controls.vpc" [$WIN32||$X360||$POSIX]
}
$Project "vice"
{
"utils\vice\vice.vpc" [$WIN32]
}
$Project "vrad_dll"
{
"utils\vrad\vrad_dll.vpc" [$WIN32]
}
$Project "vrad_launcher"
{
"utils\vrad_launcher\vrad_launcher.vpc" [$WIN32]
}
$Project "vtf2tga"
{
"utils\vtf2tga\vtf2tga.vpc" [$WIN32]
}
$Project "vtfdiff"
{
"utils\vtfdiff\vtfdiff.vpc" [$WIN32]
}
$Project "vvis_dll"
{
"utils\vvis\vvis_dll.vpc" [$WIN32]
}
$Project "vvis_launcher"
{
"utils\vvis_launcher\vvis_launcher.vpc" [$WIN32]
}
And that is it for VPC script files! All you have to do now is simply run the `createallprojects.bat` script to refresh the project. Since we added our plugin into the `$everything` group, it will only appear in the `everything` project, but you can put this elsewhere if you would like.
Visual Studio
Open the everything.sln solution. If your project was properly included, you will see your new plugin in the solution explorer. Open `myfirstplugin.cpp`. Since we removed `serverplugin_bot.cpp`, we will make one small adjustment to the code. Go to line
void Bot_RunAll( void );
and remove that line. Then find and remove the following:
if ( simulating )
{
Bot_RunAll();
}
This should then allow you to compile your new plugin! Remember to set your project to `Release` before compiling.
Congratulations! Your new plugin has been compiled and ready to be used! Navigate to `utils\myfirstplugin\Release` and you should find `myfirstplugin.dll`. You can now install this for your server. See Server plugins to set up a VDF to execute the plugin on server launch.