Creating A New Plugin

From Valve Developer Community
Jump to: navigation, search

Introduction

Note.pngNote:This article assumes you have Visual Studio 2013 or later installed and that you have a copy of the Source SDK 2013 tree downloaded on your computer.
Note.pngNote:Windows will be used in this article, but much of what is described here will also work for Linux and Mac.

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.

Icon-Important.pngImportant:This article describes how to set up a Valve Server Plugin, not a Metamod: Source plugin, much less a Sourcemod 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 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.

Icon-Important.pngImportant:Open a command prompt and launch the script file from that command prompt so that you can check if your new plugin project is properly seen by the VPC. The VPC will not list any warning or error if a typo or other mistake was made in the VPC script files; it will just ignore it. Therefore, if you do not see the project being parsed, then you will need to ensure no mistake was made in any of the 3 VPC script files that we edited.

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.