<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Hmmmmm</id>
	<title>AlliedModders Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.alliedmods.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Hmmmmm"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/Hmmmmm"/>
	<updated>2026-05-26T08:34:19Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Timers_(SourceMod_Scripting)&amp;diff=10627</id>
		<title>Timers (SourceMod Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Timers_(SourceMod_Scripting)&amp;diff=10627"/>
		<updated>2018-10-09T22:20:57Z</updated>

		<summary type="html">&lt;p&gt;Hmmmmm: Update to transitional syntax&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Timers in [[SourceMod]] are timed events that occur once or repeatedly at a given interval.&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
Timers allow you to set an interval, a function to use as the event callback, and an optional Handle to pass through the callback.  This is useful for saving data asynchronously.&lt;br /&gt;
&lt;br /&gt;
All timer functions are in &amp;lt;tt&amp;gt;plugins/include/timers.inc&amp;lt;/tt&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
=Basic Usage=&lt;br /&gt;
==One-Time Timers==&lt;br /&gt;
One-time timers are timers that only execute once.  An example of a one-time timer might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	CreateTimer(5.0, LoadStuff);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action LoadStuff(Handle timer)&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Loading stuff!&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code will print &amp;quot;Loading stuff!&amp;quot; to the server console five seconds after the map loads.  The return value has no meaning for one-time timers.&lt;br /&gt;
&lt;br /&gt;
==Repeatable Timers==&lt;br /&gt;
Repeatable timers execute infinitely many times, once every interval.  Based on the return value, they either continue or cancel.&lt;br /&gt;
&lt;br /&gt;
For example, say you want to display a message five times, once every three seconds:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
void someFunction()&lt;br /&gt;
{&lt;br /&gt;
	CreateTimer(3.0, Timer_PrintMessageFiveTimes, _, TIMER_REPEAT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Timer_PrintMessageFiveTimes(Handle timer)&lt;br /&gt;
{&lt;br /&gt;
	// Create a global variable visible only in the local scope (this function).&lt;br /&gt;
	static int numPrinted = 0;&lt;br /&gt;
&lt;br /&gt;
	if (numPrinted &amp;gt;= 5) &lt;br /&gt;
        {&lt;br /&gt;
		numPrinted = 0;&lt;br /&gt;
		return Plugin_Stop;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	PrintToServer(&amp;quot;Warning! This is a message.&amp;quot;);&lt;br /&gt;
	numPrinted++;&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Continue;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt; stops the timer, and &amp;lt;tt&amp;gt;Plugin_Continue&amp;lt;/tt&amp;gt; allows it to continue repeating.&lt;br /&gt;
&lt;br /&gt;
=Passing Data=&lt;br /&gt;
==Simple Values==&lt;br /&gt;
As mentioned earlier, timers let you pass values on to the callback function.  This value can be any type.  For example, let's say we want to print a message to a player fifteen seconds after they connect.  However, we want to cancel the timer if the player disconnects.  Implementing this is very easy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
Handle WelcomeTimers[MAXPLAYERS+1];&lt;br /&gt;
&lt;br /&gt;
public void OnClientPutInServer(int client)&lt;br /&gt;
{&lt;br /&gt;
	WelcomeTimers[client] = CreateTimer(15.0, WelcomePlayer, client);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnClientDisconnect(int client)&lt;br /&gt;
{&lt;br /&gt;
	if (WelcomeTimers[client] != null)&lt;br /&gt;
	{&lt;br /&gt;
		KillTimer(WelcomeTimers[client]);&lt;br /&gt;
		WelcomeTimers[client] = null;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action WelcomePlayer(Handle timer, any client)&lt;br /&gt;
{&lt;br /&gt;
	PrintToConsole(client, &amp;quot;Welcome to the server!&amp;quot;);&lt;br /&gt;
	WelcomeTimers[client] = null;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Another example without using handles is to use either UserID or ClientSerial (which is unique to each player):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
public void OnClientPutInServer(int client)&lt;br /&gt;
{&lt;br /&gt;
	CreateTimer(15.0, WelcomePlayer, GetClientSerial(client)); // You could also use GetClientUserId(client)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action WelcomePlayer(Handle timer, any serial)&lt;br /&gt;
{&lt;br /&gt;
	int client = GetClientFromSerial(serial); // Validate the client serial&lt;br /&gt;
	&lt;br /&gt;
	if (client == 0) // The serial is no longer valid, the player must have disconnected&lt;br /&gt;
	{&lt;br /&gt;
		return Plugin_Stop;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	PrintToConsole(client, &amp;quot;Welcome to the server!&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
If you want to close or cancel a timer when a client disconnects, then use the first example with handles.&lt;br /&gt;
&lt;br /&gt;
==Handles==&lt;br /&gt;
If you want to pass a Handle as a value, you have the option of using &amp;lt;tt&amp;gt;TIMER_DATA_HNDL_CLOSE&amp;lt;/tt&amp;gt;, which will automatically call &amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; for you once the timer dies.  &lt;br /&gt;
&lt;br /&gt;
==Data Packs==&lt;br /&gt;
Data packs are packable structures that can be used to hold asynchronous data (data that must be saved and unpacked for later).  They are especially useful for timers, and thus there exists a helper function, called &amp;lt;tt&amp;gt;CreateDataTimer()&amp;lt;/tt&amp;gt;, which creates a timer using a data pack handle.  The handle is created and closed automatically for you.&lt;br /&gt;
&lt;br /&gt;
The above example could be rewritten as:&lt;br /&gt;
&amp;lt;pawn&amp;gt;&lt;br /&gt;
Handle WelcomeTimers[MAXPLAYERS+1];&lt;br /&gt;
&lt;br /&gt;
public void OnClientPutInServer(int client)&lt;br /&gt;
{&lt;br /&gt;
	DataPack pack;&lt;br /&gt;
	WelcomeTimers[client] = CreateDataTimer(15.0, WelcomePlayer, pack);&lt;br /&gt;
	pack.WriteCell(client);&lt;br /&gt;
	pack.WriteString(&amp;quot;Welcome to the server!&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnClientDisconnect(int client)&lt;br /&gt;
{&lt;br /&gt;
	if (WelcomeTimers[client] != null)&lt;br /&gt;
	{&lt;br /&gt;
		KillTimer(WelcomeTimers[client]);&lt;br /&gt;
		WelcomeTimers[client] = null;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action WelcomePlayer(Handle timer, DataPack pack)&lt;br /&gt;
{&lt;br /&gt;
	char str[128];&lt;br /&gt;
	int client;&lt;br /&gt;
&lt;br /&gt;
	/* Set to the beginning and unpack it */&lt;br /&gt;
	pack.Reset();&lt;br /&gt;
	client = pack.ReadCell();&lt;br /&gt;
	pack.ReadString(str, sizeof(str));&lt;br /&gt;
	PrintToConsole(client, &amp;quot;%s&amp;quot;, str);&lt;br /&gt;
	WelcomeTimers[client] = null;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Notes=&lt;br /&gt;
==Accuracy==&lt;br /&gt;
The smallest possible interval is 0.1 seconds.  Timers have high precision (floating point) but low accuracy, as the current time is based on the in-game tick count, not the system clock.  This has two implications:&lt;br /&gt;
*If the server is paused (not ticking or hibernating), timers will not run.&lt;br /&gt;
*The server will not always tick at an exact interval.  &lt;br /&gt;
&lt;br /&gt;
For example, a 1.234 second interval timer starting from time &amp;lt;tt&amp;gt;t&amp;lt;/tt&amp;gt; might not tick until &amp;lt;tt&amp;gt;t+1.242&amp;lt;/tt&amp;gt; at a tickrate of 66 ticks per second.&lt;br /&gt;
&lt;br /&gt;
==Timer Death==&lt;br /&gt;
All timers are guaranteed to die either by:&lt;br /&gt;
*&amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; being called (or on plugin unload);&lt;br /&gt;
*&amp;lt;tt&amp;gt;KillTimer()&amp;lt;/tt&amp;gt; being called;&lt;br /&gt;
*&amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt; being returned from a repeatable timer;&lt;br /&gt;
*&amp;lt;tt&amp;gt;TriggerTimer()&amp;lt;/tt&amp;gt; being called on a one-time timer;&lt;br /&gt;
*Execution of a one-time timer finishes.&lt;br /&gt;
&lt;br /&gt;
When a timer dies, if &amp;lt;tt&amp;gt;TIMER_DATA_HNDL_CLOSE&amp;lt;/tt&amp;gt; is set, the Handle will always be closed with the permissions that &amp;lt;tt&amp;gt;CloseHandle()&amp;lt;/tt&amp;gt; uses by default.  Since timers cannot be cloned, there should be no ownership issues.&lt;br /&gt;
&lt;br /&gt;
==Changing Intervals==&lt;br /&gt;
The interval of a timer cannot be changed as of this writing.  The timer must be killed and a new one created.&lt;br /&gt;
&lt;br /&gt;
==AMX Mod X==&lt;br /&gt;
Unlike [[AMX Mod X]]'s &amp;lt;tt&amp;gt;set_task&amp;lt;/tt&amp;gt; function, you cannot pass arrays using &amp;lt;tt&amp;gt;CreateTimer&amp;lt;/tt&amp;gt;.  To accomplish this, you should use the data pack functionality explained above.&lt;br /&gt;
&lt;br /&gt;
Similarly, there are no flags for counted repeats (non-infinite loops) or timers based on the map start or end.  These must be done manually.&lt;br /&gt;
&lt;br /&gt;
=External Links=&lt;br /&gt;
*[http://www.sourcemod.net/devlog/?p=130 On Timer Design, Part 3] (SourceMod DevLog)&lt;br /&gt;
*[http://www.sourcemod.net/devlog/?p=119 On Timer Design, Part 2] (SourceMod DevLog)&lt;br /&gt;
*[http://www.sourcemod.net/devlog/?p=118 On Timer Design, Part 1] (SourceMod DevLog)&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Hmmmmm</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Menus_Step_By_Step_(SourceMod_Scripting)&amp;diff=10622</id>
		<title>Menus Step By Step (SourceMod Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Menus_Step_By_Step_(SourceMod_Scripting)&amp;diff=10622"/>
		<updated>2018-10-02T00:12:32Z</updated>

		<summary type="html">&lt;p&gt;Hmmmmm: GetInfo -&amp;gt; GetItem&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The SourceMod [[Menu API (SourceMod)|Menu API]] is fairly useful for displaying an information panel, a menu, or a vote to users.  This document talks specifically about menus and how to create one.&lt;br /&gt;
&lt;br /&gt;
== The working menu example ==&lt;br /&gt;
&lt;br /&gt;
This is the working code example that we'll be talking about in the upcoming sections.  If you need to, you can come back and look at it as you read the rest of this page.&lt;br /&gt;
&lt;br /&gt;
We will be using PrintToServer to print text to the server console as we run through the events.&lt;br /&gt;
&lt;br /&gt;
Usage of the [[Translations (SourceMod Scripting)|Translations]] system is highly recommended and will be used in this example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;#define CHOICE1 &amp;quot;#choice1&amp;quot;&lt;br /&gt;
#define CHOICE2 &amp;quot;#choice2&amp;quot;&lt;br /&gt;
#define CHOICE3 &amp;quot;#choice3&amp;quot;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	LoadTranslations(&amp;quot;menu_test.phrases&amp;quot;);&lt;br /&gt;
	RegConsoleCmd(&amp;quot;menu_test1&amp;quot;, Menu_Test1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public int MenuHandler1(Menu menu, MenuAction action, int param1, int param2)&lt;br /&gt;
{&lt;br /&gt;
	switch(action)&lt;br /&gt;
	{&lt;br /&gt;
		case MenuAction_Start:&lt;br /&gt;
		{&lt;br /&gt;
			PrintToServer(&amp;quot;Displaying menu&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		case MenuAction_Display:&lt;br /&gt;
		{&lt;br /&gt;
	 		char buffer[255];&lt;br /&gt;
			Format(buffer, sizeof(buffer), &amp;quot;%T&amp;quot;, &amp;quot;Vote Nextmap&amp;quot;, param1);&lt;br /&gt;
&lt;br /&gt;
			Panel panel = view_as&amp;lt;Panel&amp;gt;(param2);&lt;br /&gt;
			panel.SetTitle(buffer);&lt;br /&gt;
			PrintToServer(&amp;quot;Client %d was sent menu with panel %x&amp;quot;, param1, param2);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		case MenuAction_Select:&lt;br /&gt;
		{&lt;br /&gt;
			char info[32];&lt;br /&gt;
			menu.GetItem(param2, info, sizeof(info));&lt;br /&gt;
			if (StrEqual(info, CHOICE3))&lt;br /&gt;
			{&lt;br /&gt;
				PrintToServer(&amp;quot;Client %d somehow selected %s despite it being disabled&amp;quot;, param1, info);&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				PrintToServer(&amp;quot;Client %d selected %s&amp;quot;, param1, info);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		case MenuAction_Cancel:&lt;br /&gt;
		{&lt;br /&gt;
			PrintToServer(&amp;quot;Client %d's menu was cancelled for reason %d&amp;quot;, param1, param2);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		case MenuAction_End:&lt;br /&gt;
		{&lt;br /&gt;
			delete menu;&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		case MenuAction_DrawItem:&lt;br /&gt;
		{&lt;br /&gt;
			int style;&lt;br /&gt;
			char info[32];&lt;br /&gt;
			menu.GetItem(param2, info, sizeof(info), style);&lt;br /&gt;
			&lt;br /&gt;
			if (StrEqual(info, CHOICE3))&lt;br /&gt;
			{&lt;br /&gt;
				return ITEMDRAW_DISABLED;&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				return style;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		case MenuAction_DisplayItem:&lt;br /&gt;
		{&lt;br /&gt;
			char info[32];&lt;br /&gt;
			menu.GetItem(param2, info, sizeof(info));&lt;br /&gt;
			&lt;br /&gt;
			char display[64];&lt;br /&gt;
			&lt;br /&gt;
			if (StrEqual(info, CHOICE3))&lt;br /&gt;
			{&lt;br /&gt;
				Format(display, sizeof(display), &amp;quot;%T&amp;quot;, &amp;quot;Choice 3&amp;quot;, param1);&lt;br /&gt;
				return RedrawMenuItem(display);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Menu_Test1(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	Menu menu = new Menu(MenuHandler1, MENU_ACTIONS_ALL);&lt;br /&gt;
	menu.SetTitle(&amp;quot;%T&amp;quot;, &amp;quot;Menu Title&amp;quot;, LANG_SERVER);&lt;br /&gt;
	menu.AddItem(CHOICE1, &amp;quot;Choice 1&amp;quot;);&lt;br /&gt;
	menu.AddItem(CHOICE2, &amp;quot;Choice 2&amp;quot;);&lt;br /&gt;
	menu.AddItem(CHOICE3, &amp;quot;Choice 3&amp;quot;);&lt;br /&gt;
	menu.ExitButton = false;&lt;br /&gt;
	menu.Display(client, 20);&lt;br /&gt;
	&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The translation file that goes with it... addons/sourcemod/translations/menu_test.phrases.txt&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;Phrases&amp;quot;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;Choice 3&amp;quot;&lt;br /&gt;
	{&lt;br /&gt;
		&amp;quot;en&amp;quot;	&amp;quot;Choice Translated&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	&amp;quot;Menu Title&amp;quot;&lt;br /&gt;
	{&lt;br /&gt;
		&amp;quot;en&amp;quot;	&amp;quot;Menu Title Translated&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Step by Step ==&lt;br /&gt;
&lt;br /&gt;
=== OnPluginStart ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	LoadTranslations(&amp;quot;menu_test.phrases&amp;quot;);&lt;br /&gt;
	RegConsoleCmd(&amp;quot;menu_test1&amp;quot;, Menu_Test1);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This block is here to register the command /menu_test1 so that this menu can be tested.&lt;br /&gt;
&lt;br /&gt;
This block is beyond the scope of this page.  See: [[Introduction to SourceMod Plugins#Plugin Structure|Plugin Structure]] for OnPluginStart, [[Translations (SourceMod Scripting)|Translations]] for LoadTranslations, and [[Commands_(SourceMod_Scripting)|Commands]] for RegConsoleCmd.&lt;br /&gt;
&lt;br /&gt;
=== Menu_Test1 ===&lt;br /&gt;
&lt;br /&gt;
Menu_Test1 is a ConCmd, which is beyond the scope of this page.  See: [[Commands (SourceMod Scripting)|Commands]] for more details on that.  We're going to be talking about what's in it.&lt;br /&gt;
&lt;br /&gt;
==== Menu ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;	Menu menu = new Menu(MenuHandler1, MENU_ACTIONS_ALL);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Menu takes two arguments.&lt;br /&gt;
&lt;br /&gt;
The first is a function that matches the [https://sm.alliedmods.net/new-api/menus/MenuHandler MenuHandler] callback signature.&lt;br /&gt;
&lt;br /&gt;
The second is a bitmask of which MenuAction events we are going to handle in our MenuHandler.  There are 7 that apply to standard menus: &lt;br /&gt;
* MenuAction_Start - Called once when a menu is displayed&lt;br /&gt;
* MenuAction_Display - Called once for each client a menu is displayed to&lt;br /&gt;
* MenuAction_Select - Called when a client makes a selection from the menu that isn't Previous, Next, Back, or Exit.&lt;br /&gt;
* MenuAction_Cancel - Called when a client closes a menu or it is closed on them&lt;br /&gt;
* MenuAction_End - Called once when all clients have closed the menu&lt;br /&gt;
* MenuAction_DrawItem - Called once for each item for each user a menu is displayed to. Can change the menu item style.&lt;br /&gt;
* MenuAction_DisplayIitem. - Called once for each item for each user a menu is displayed to. Can change the menu item text.&lt;br /&gt;
&lt;br /&gt;
These will be discussed in more detail in the MenuHandler1 section.&lt;br /&gt;
&lt;br /&gt;
Of those 7, 3 are called whether you specify them or not: MenuAction_Select, MenuAction_Cancel, and MenuAction_End.&lt;br /&gt;
&lt;br /&gt;
MENU_ACTIONS_DEFAULT sets just the 3 required fields, while MENU_ACTIONS_ALL specifies all 10 actions (including the 3 vote actions).&lt;br /&gt;
&lt;br /&gt;
To specify just a few of them, you can do this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;	Menu menu = new Menu(MenuHandler1, MenuAction_Start|MenuAction_Select|MenuAction_Cancel|MenuAction_End);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== menu.SetTitle ====&lt;br /&gt;
&amp;lt;pawn&amp;gt;	menu.SetTitle(&amp;quot;%T&amp;quot;, &amp;quot;Menu Title&amp;quot;, LANG_SERVER);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sets the menu's title.  This example uses the translation system and the server's default language.  This isn't strictly necessary as we will set the menu title again later.&lt;br /&gt;
&lt;br /&gt;
==== menu.AddItem ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;	menu.AddItem(CHOICE1, &amp;quot;Choice 1&amp;quot;);&lt;br /&gt;
	menu.AddItem(CHOICE2, &amp;quot;Choice 2&amp;quot;);&lt;br /&gt;
	menu.AddItem(CHOICE3, &amp;quot;Choice 3&amp;quot;);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A menu isn't useful without something in it!&lt;br /&gt;
menu.AddItem has 2 required arguments and one optional argument.&lt;br /&gt;
&lt;br /&gt;
The 2 required arguments are:&lt;br /&gt;
&lt;br /&gt;
The Info string, and the Display string.&lt;br /&gt;
&lt;br /&gt;
The Info String is a string that is used to uniquely identify this menu item.  It is never displayed to the user, but is used in various callbacks.&lt;br /&gt;
&lt;br /&gt;
The Display String is the default text to be used for this item on the menu.  It can be changed via the menu's MenuAction_DisplayItem callback.&lt;br /&gt;
&lt;br /&gt;
The optional argument is the menu's item draw style.  It can be one of these values:&lt;br /&gt;
* ITEMDRAW_DEFAULT - Displays text as normal.&lt;br /&gt;
* ITEMDRAW_DISABLED - Item is displayed and has a number, but can't be selected.&lt;br /&gt;
* ITEMDRAW_RAWLINE - Item is displayed, but doesn't have a number assigned to it and thus can't be selected&lt;br /&gt;
* ITEMDRAW_NOTEXT - Draws an item with no text.  Not very useful.&lt;br /&gt;
* ITEMDRAW_SPACER - Item is blank, but has a number.  Can't be selected.&lt;br /&gt;
* ITEMDRAW_IGNORE - Item is blank with no number.  Can't be selected.&lt;br /&gt;
* ITEMDRAW_CONTROL - Don't use this one.  It's used for the items SourceMod automatically adds.&lt;br /&gt;
&lt;br /&gt;
Be aware that if your CreateMenu second argument includes MenuAction_DrawItem or MENU_ACTIONS_ALL and you don't actually implement the MenuAction_DrawItem callback (or implement it and don't return the current item's style if you don't change it), your style here will be completely ignored.&lt;br /&gt;
&lt;br /&gt;
==== menu.ExitButton ====&lt;br /&gt;
&amp;lt;pawn&amp;gt; 	menu.ExitButton = false;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Defaults to true.&lt;br /&gt;
&lt;br /&gt;
It set to false, the menu won't have an exit button.&lt;br /&gt;
&lt;br /&gt;
==== menu.ExitBackButton ====&lt;br /&gt;
&amp;lt;pawn&amp;gt; 	menu.ExitBackButton = false;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(This isn't in the code above, but it should be mentioned) &lt;br /&gt;
&lt;br /&gt;
Defaults to false.&lt;br /&gt;
&lt;br /&gt;
Should only be used if the menu is a submenu, with the menu set up to check the cancel reason to see if the ExitBack action was used.&lt;br /&gt;
&lt;br /&gt;
If set to true, replaces the Exit item with the Back item.  The Back item still cancels the menu, but has a separate cancel reason.&lt;br /&gt;
&lt;br /&gt;
This can be used to dynamically set if a menu is being called as its own menu or as a submenu.&lt;br /&gt;
&lt;br /&gt;
==== menu.Display ====&lt;br /&gt;
&amp;lt;pawn&amp;gt; 	menu.Display(client, 20);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
DisplayMenu takes 2 arguments:&lt;br /&gt;
&lt;br /&gt;
A Menu handle, a client index, and the amount of time in seconds to show the menu.&lt;br /&gt;
&lt;br /&gt;
If you want the menu to show forever, pass MENU_TIME_FOREVER as the third argument.&lt;br /&gt;
&lt;br /&gt;
=== MenuHandler1 ===&lt;br /&gt;
&amp;lt;pawn&amp;gt;public int MenuHandler1(Menu menu, MenuAction action, int param1, int param2)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MenuHandler1 is a function whose signature matches the MenuHandler callback.  It can be named something other than MenuHandler1. It must always be public and it will always have these arguments: Handle, MenuAction, cell, and cell in that order.&lt;br /&gt;
&lt;br /&gt;
The Handle argument is always the menu that called the handler.&lt;br /&gt;
&lt;br /&gt;
The MenuAction argument is always one of 7 actions for a standard menu.  They are:  MenuAction_Start, MenuAction_Display, MenuAction_Select, MenuAction_Cancel, MenuAction_End, MenuAction_DrawItem, and MenuAction_DisplayIitem.  We will discuss each of these as we reach their code.&lt;br /&gt;
&lt;br /&gt;
The two cell arguments meaning depend on the MenuAction argument. '''A common mistake is to assume param1 is the client.''' This is incorrect for MenuAction_Start, MenuAction_End, MenuAction_VoteEnd, MenuAction_VoteStart, and MenuAction_VoteCancel.&lt;br /&gt;
&lt;br /&gt;
==== MenuAction_Start ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;		case MenuAction_Start:&lt;br /&gt;
		{&lt;br /&gt;
			PrintToServer(&amp;quot;Displaying menu&amp;quot;);&lt;br /&gt;
		}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* param1: not set&lt;br /&gt;
* param2: not set&lt;br /&gt;
* return: 0 (or don't return)&lt;br /&gt;
&lt;br /&gt;
MenuAction_Start doesn't set param1 and param2.  It is fired when the menu is displayed to one or more users using DisplayMenu, DisplayMenuAtItem, VoteMenu, or VoteMenuToAll.&lt;br /&gt;
&lt;br /&gt;
==== MenuAction_Display ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;		case MenuAction_Display:&lt;br /&gt;
		{&lt;br /&gt;
	 		char buffer[255];&lt;br /&gt;
			Format(buffer, sizeof(buffer), &amp;quot;%T&amp;quot;, &amp;quot;Vote Nextmap&amp;quot;, param1);&lt;br /&gt;
&lt;br /&gt;
			Panel panel = view_as&amp;lt;Panel&amp;gt;(param2);&lt;br /&gt;
			panel.SetTitle(buffer);&lt;br /&gt;
			PrintToServer(&amp;quot;Client %d was sent menu with panel %x&amp;quot;, param1, param2);&lt;br /&gt;
		}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* param1: client index&lt;br /&gt;
* param2: MenuPanel Handle&lt;br /&gt;
* return: 0 (or don't return)&lt;br /&gt;
&lt;br /&gt;
MenuAction_Display is called once for each user a menu is displayed to.  param1 is the client, param2 is the MenuPanel handle.&lt;br /&gt;
&lt;br /&gt;
SetPanelTitle is used to change the menu's title based on the language of the user viewing it using the Translations system.  Previous versions of this guide suggested using SetMenuTitle.  This is a ''bad'' idea, as it changes the title globally.&lt;br /&gt;
&lt;br /&gt;
==== MenuAction_Select ====&lt;br /&gt;
&amp;lt;pawn&amp;gt;		case MenuAction_Select:&lt;br /&gt;
		{&lt;br /&gt;
			char info[32];&lt;br /&gt;
			menu.GetItem(param2, info, sizeof(info));&lt;br /&gt;
			if (StrEqual(info, CHOICE3))&lt;br /&gt;
			{&lt;br /&gt;
				PrintToServer(&amp;quot;Client %d somehow selected %s despite it being disabled&amp;quot;, param1, info);&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				PrintToServer(&amp;quot;Client %d selected %s&amp;quot;, param1, info);&lt;br /&gt;
			}&lt;br /&gt;
		}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* param1: client index&lt;br /&gt;
* param2: item number for use with GetMenuItem&lt;br /&gt;
* return: 0 (or don't return)&lt;br /&gt;
&lt;br /&gt;
MenuAction_Select is called when a user selects a non-control item on the menu (something added using AddMenuItem). param1 is the client, param2 is the menu position of the item the client selected.&lt;br /&gt;
&lt;br /&gt;
Using the item position to check which item was selected is a bad idea, as item position is brittle and will break things if AddMenuItem or InsertMenuItem is used.  It is recommended that you instead use the Menu item's info string, as done in the code above.&lt;br /&gt;
&lt;br /&gt;
GetMenuItem is used here to fetch the info string.&lt;br /&gt;
&lt;br /&gt;
==== MenuAction_Cancel ====&lt;br /&gt;
&lt;br /&gt;
		case MenuAction_Cancel:&lt;br /&gt;
		{&lt;br /&gt;
			PrintToServer(&amp;quot;Client %d's menu was cancelled for reason %d&amp;quot;, param1, param2);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
* param1: client index&lt;br /&gt;
* param2: MenuCancel reason&lt;br /&gt;
* return: 0 (or don't return)&lt;br /&gt;
&lt;br /&gt;
MenuAction_Cancel is called whenever a user closes a menu or it is closed for them for another reason.  param1 is the client, param2 is the close reason.&lt;br /&gt;
&lt;br /&gt;
The close reasons you can receive are:&lt;br /&gt;
&lt;br /&gt;
* MenuCancel_Disconnected - The client got disconnected from the server.&lt;br /&gt;
* MenuCancel_Interrupted - Another menu opened, automatically closing our menu.&lt;br /&gt;
* MenuCancel_Exit - The client selected Exit. Not called if SetMenuExitBack was set to true. Not called if SetMenuExit was set to false.&lt;br /&gt;
* MenuCancel_NoDisplay - Our menu never displayed to the client for whatever reason.&lt;br /&gt;
* MenuCancel_Timeout - The menu timed out. Not called if the menu time was MENU_TIME_FOREVER.&lt;br /&gt;
* MenuCancel_ExitBack - The client selected Back. Only called if SetMenuExitBack has been called and set to true before the menu was sent. Not called if SetMenuExit was set to false.&lt;br /&gt;
&lt;br /&gt;
==== MenuAction_End ====&lt;br /&gt;
&amp;lt;pawn&amp;gt;		case MenuAction_End:&lt;br /&gt;
		{&lt;br /&gt;
			delete menu;&lt;br /&gt;
		}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* param1: MenuEnd reason&lt;br /&gt;
* param2: If param1 is MenuEnd_Cancelled, the MenuCancel reason&lt;br /&gt;
* return: 0 (or don't return)&lt;br /&gt;
&lt;br /&gt;
MenuAction_End is called when ''all'' clients have closed a menu or vote.  For menus that are not going to be redisplayed, it is required that you call CloseHandle on the menu here.&lt;br /&gt;
&lt;br /&gt;
The parameters are rarely used in MenuAction_End.  param1 is the menu end reason. param2 depends on param1.&lt;br /&gt;
&lt;br /&gt;
The end reasons you can receive for normal menus are:&lt;br /&gt;
&lt;br /&gt;
* MenuEnd_Selected - The menu closed because an item was selected (MenuAction_Select was fired)&lt;br /&gt;
* MenuEnd_Cancelled - The menu was cancelled (MenuAction_Cancel was fired), cancel reason is in param2; cancel reason can be any of the ones listed in MenuAction_Cancel except MenuCancel_Exit or MenuCancel_ExitBack&lt;br /&gt;
* MenuEnd_Exit - The menu was exited via the Exit item (MenuAction_Cancel was fired with param2 set to MenuCancel_Exit)&lt;br /&gt;
* MenuEnd_ExitBack - The menu was exited via the ExitBack item (MenuAction_Cancel was fired with param 2 set to MenuCancel_ExitBack)&lt;br /&gt;
&lt;br /&gt;
Note: You do '''not''' have the client index during this callback, so it's far too late to do anything useful with this information.&lt;br /&gt;
&lt;br /&gt;
==== MenuAction_DrawItem ====&lt;br /&gt;
&amp;lt;pawn&amp;gt;		case MenuAction_DrawItem:&lt;br /&gt;
		{&lt;br /&gt;
			int style;&lt;br /&gt;
			char info[32];&lt;br /&gt;
			menu.GetItem(param2, info, sizeof(info), style);&lt;br /&gt;
			&lt;br /&gt;
			if (StrEqual(info, CHOICE3))&lt;br /&gt;
			{&lt;br /&gt;
				return ITEMDRAW_DISABLED;&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				return style;&lt;br /&gt;
			}&lt;br /&gt;
		}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* param1: client index&lt;br /&gt;
* param2: item number for use with GetMenuItem&lt;br /&gt;
* return: new ITEMDRAW properties or style from GetMenuItem.  Since 0 is ITEMDRAW_DEFAULT, returning 0 clears all styles for this item.&lt;br /&gt;
&lt;br /&gt;
MenuAction_DrawItem is called once for each item on the menu for each user.  You can manipulate its draw style here. param1 is the client, param2 is the menu position.&lt;br /&gt;
&lt;br /&gt;
Using the item position to check which item was selected is a bad idea, as item position is brittle and will break things if AddMenuItem or InsertMenuItem is used.  It is recommended that you instead use the Menu item's info string, as done in the code above.&lt;br /&gt;
&lt;br /&gt;
GetMenuItem is used here to fetch the info string and menu style.&lt;br /&gt;
&lt;br /&gt;
You should return the style you want the menu item to have.  In our example, if client 1 is viewing the menu, we want CHOICE3 to be disabled.&lt;br /&gt;
&lt;br /&gt;
the return value is a bitfield, so to apply multiple styles, you do something like this:&lt;br /&gt;
&lt;br /&gt;
		return ITEMDRAW_NOTEXT | ITEMDRAW_SPACER;&lt;br /&gt;
&lt;br /&gt;
'''Failing to return the current item's style if you don't change the style is a programmer error.'''&lt;br /&gt;
&lt;br /&gt;
==== MenuAction_DisplayItem ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;		case MenuAction_DisplayItem:&lt;br /&gt;
		{&lt;br /&gt;
			char info[32];&lt;br /&gt;
			menu.GetItem(param2, info, sizeof(info));&lt;br /&gt;
			&lt;br /&gt;
			char display[64];&lt;br /&gt;
			&lt;br /&gt;
			if (StrEqual(info, CHOICE3))&lt;br /&gt;
			{&lt;br /&gt;
				Format(display, sizeof(display), &amp;quot;%T&amp;quot;, &amp;quot;Choice 3&amp;quot;, param1);&lt;br /&gt;
				return RedrawMenuItem(display);&lt;br /&gt;
			}&lt;br /&gt;
		}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* param1: client index&lt;br /&gt;
* param2: item number for use with GetMenuItem&lt;br /&gt;
* return: return value from RedrawMenuItem or 0 for no change&lt;br /&gt;
&lt;br /&gt;
MenuAction_DrawItem is called once for each item on the menu for each user.  You can manipulate its text here. param1 is the client, param2 is the menu position.&lt;br /&gt;
&lt;br /&gt;
This callback is intended for use with the Translation system.&lt;br /&gt;
&lt;br /&gt;
Using the item position to check which item was selected is a bad idea, as item position is brittle and will break things if AddMenuItem or InsertMenuItem is used.  It is recommended that you instead use the Menu item's info string, as done in the code above.&lt;br /&gt;
&lt;br /&gt;
GetMenuItem is used here to fetch the info string.&lt;br /&gt;
&lt;br /&gt;
Once we have the info string, we compare our item to it and apply the appropriate translation string.&lt;br /&gt;
&lt;br /&gt;
If we change an item, we have to call RedrawMenuItem and return the value it returns.  If we do not change an item, we must return 0.&lt;br /&gt;
&lt;br /&gt;
==== return ====&lt;br /&gt;
&amp;lt;pawn&amp;gt;	return 0;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you handle MenuAction_DrawItem or MenuAction_DisplayItem, you will get the following warning if you fail to return 0 after the switch block:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;warning 209: function &amp;quot;MenuHandler1&amp;quot; should return a value&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is because MenuAction_DrawItem and MenuAction_DisplayItem have return values, while the other actions only return 0.&lt;br /&gt;
&lt;br /&gt;
== The End ==&lt;br /&gt;
Hopefully this walk through a simple menu helped you understand why each call is being made where.  Menus have some options that we didn't explore here, such as disabling pagination (which is enabled by default).  You may want to refer to the main Menu documentation for more details.&lt;/div&gt;</summary>
		<author><name>Hmmmmm</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Writing_Extensions&amp;diff=10505</id>
		<title>Writing Extensions</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Writing_Extensions&amp;diff=10505"/>
		<updated>2018-01-31T14:54:41Z</updated>

		<summary type="html">&lt;p&gt;Hmmmmm: Updated sourcepawn sections to new syntax&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SourceMod's Extension System is a powerful way to greatly enhance the flexibility of your SourceMod plugins.  You can take full advantage of SourceMod's Core, using the interfaces it provides, to create C++ plugins, plugin events, plugin native functions, and shared interfaces.  Extensions can also hook into Metamod:Source.&lt;br /&gt;
&lt;br /&gt;
This article goes into the details of creating a SourceMod Extension.  Knowledge of C++ is required.&lt;br /&gt;
&lt;br /&gt;
=SDK Structure=&lt;br /&gt;
First, download the [[SourceMod SDK]] from the [https://github.com/alliedmodders/sourcemod/releases SourceMod github], and one of the SDKs from the [https://github.com/alliedmodders/hl2sdk hl2sdk github]. The directory structure should contain these folders:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
* hl2sdk-something - One of the HL2 SDKs&lt;br /&gt;
* sourcemod-version - The sourcemod package&lt;br /&gt;
** extensions - Sourcemod Extensions code&lt;br /&gt;
*** curl - Source code to the cURL extension&lt;br /&gt;
*** geoip - Source code to the GeoIP extension&lt;br /&gt;
*** mysql - Source code to the MySQL extension&lt;br /&gt;
** plugins - Source code to all of SourceMod's plugins&lt;br /&gt;
*** include - The include files which document plugin API&lt;br /&gt;
** public - Interface files for SourceMod's Core Interfaces&lt;br /&gt;
*** extensions  - Interfaces that are provided by extensions&lt;br /&gt;
*** '''sample_ext''' - The Sample Extension SDK&lt;br /&gt;
**** extension.cpp - Sample C++ plugin&lt;br /&gt;
**** extension.h - Sample C++ header file&lt;br /&gt;
**** Makefile - Sample C++ plugin compiler&lt;br /&gt;
**** smsdk_config.h - Sample C++ plugin settings&lt;br /&gt;
** sourcepawn - The include/interface files for SourcePawn&lt;br /&gt;
*** compiler - The SourcePawn Compiler&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Starting an Extension=&lt;br /&gt;
For simplicity, this article will assume you are using the SDK base files. Navigate to &amp;lt;code&amp;gt;extensions/public/sample_ext&amp;lt;/code&amp;gt;, and ensure that you can compile your code. If using the command line, &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; should do this, if using Visual Studio, see [[#Setting up Visual Studio|Setting up Visual Studio]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The first step of creating your extension is to configure it.  Open the &amp;lt;tt&amp;gt;smsdk_config.h&amp;lt;/tt&amp;gt; file and edit each of the following defines.  Use the information below to guide you.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
*SMEXT_CONF_NAME - The general name for your Extension (should be short).&lt;br /&gt;
*SMEXT_CONF_DESCRIPTION - A short description of what your extension does.&lt;br /&gt;
*SMEXT_CONF_VERSION - A version number string.  By convention, SourceMod uses the four set build number notation, so build 1.2.3.4 means:&lt;br /&gt;
**1 is the &amp;quot;Major&amp;quot; release version.&lt;br /&gt;
**2 is the &amp;quot;Minor&amp;quot; release version.&lt;br /&gt;
**3 is the &amp;quot;Maintenance&amp;quot; or &amp;quot;Revision&amp;quot; version.&lt;br /&gt;
**4 is the &amp;quot;Build,&amp;quot; usually an internal source control number.&lt;br /&gt;
*SMEXT_CONF_AUTHOR - Your name (or whoever/whatever authored the plugin).&lt;br /&gt;
*SMEXT_CONF_URL - The URL/homepage of this extension.&lt;br /&gt;
*SMEXT_CONF_LOGTAG - The logtag your extension will use for SourceMod logging.  By convention, try to keep this under ten characters or so, and to make it all caps.&lt;br /&gt;
*SMEXT_CONF_LICENSE - Right now, the SourceMod Dev Team mandates that 3rd party extensions must be under an Open Source license.  Putting a license abbreviation or very short message here is appropriate.  For more information, see [https://www.sourcemod.net/license.php the SourceMod license].&lt;br /&gt;
*SMEXT_CONF_DATESTRING - You do not need to modify this.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
If your plugin requires using SourceHook or Metamod:Source, uncomment this line:&lt;br /&gt;
&amp;lt;code&amp;gt;#define SMEXT_CONF_METAMOD&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Next, you should change the name of your extension. By convention, your extension's class name should start with a capital letter.&lt;br /&gt;
* First, open &amp;lt;code&amp;gt;extension.h&amp;lt;/code&amp;gt; and change &amp;quot;Sample&amp;quot; in this line:&lt;br /&gt;
&amp;lt;cpp&amp;gt;class Sample : public SDKExtension&amp;lt;/cpp&amp;gt;&lt;br /&gt;
* Next, open &amp;lt;code&amp;gt;extension.cpp&amp;lt;/code&amp;gt; change these two lines:&lt;br /&gt;
&amp;lt;cpp&amp;gt;Sample g_Sample;&lt;br /&gt;
SMEXT_LINK(&amp;amp;g_Sample);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Visual Studio Users==&lt;br /&gt;
Make sure you change the name of your &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; file.  The naming convention for SourceMod extensions is &amp;lt;tt&amp;gt;name.ext.dll&amp;lt;/tt&amp;gt;, where &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; is a short name for your extension.  You are free to change this, but it is highly recommended that you keep the &amp;lt;tt&amp;gt;.ext.dll&amp;lt;/tt&amp;gt; intact.&lt;br /&gt;
&lt;br /&gt;
You can do this by going to &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; -&amp;gt; &amp;lt;tt&amp;gt;Properties&amp;lt;/tt&amp;gt; -&amp;gt; &amp;lt;tt&amp;gt;Configuration Properties&amp;lt;/tt&amp;gt; -&amp;gt; &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; -&amp;gt; &amp;lt;tt&amp;gt;General&amp;lt;/tt&amp;gt;.  Set the &amp;lt;tt&amp;gt;Output File&amp;lt;/tt&amp;gt; option appropriately.&lt;br /&gt;
&lt;br /&gt;
==Linux Users==&lt;br /&gt;
Simply edit the &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; and change the &amp;lt;tt&amp;gt;BINARY&amp;lt;/tt&amp;gt; line near the top.  Make sure you do not add any trailing spaces at the end of the name, or the build won't come out right.&lt;br /&gt;
&lt;br /&gt;
You should now be able to compile a blank extension!&lt;br /&gt;
&lt;br /&gt;
=Creating Native Functions=&lt;br /&gt;
''Main article: [[Natives (SourceMod Development)]]''&lt;br /&gt;
&lt;br /&gt;
Most of the time, an extension exists to add &amp;quot;native functions&amp;quot; to the plugin system.  Native functions are simply the functions that plugins can use in SourceMod.  They are coded in C++ and have a short prototype declaration in an include file.&lt;br /&gt;
&lt;br /&gt;
==Prototyping==&lt;br /&gt;
The first step to creating a native is to &amp;lt;tt&amp;gt;spec it&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;prototype&amp;lt;/tt&amp;gt; it.  This is a simple but often time consuming process, but if you get in the habit of it, your documentation will be much better.  Let's first create a very simply native.  Here is a prototype for it, which we will place in &amp;lt;tt&amp;gt;sample.inc&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Returns the square of a number.&lt;br /&gt;
 *&lt;br /&gt;
 * @param num	Number to square.&lt;br /&gt;
 * @return	The square of num.&lt;br /&gt;
 */&lt;br /&gt;
native int SquareNumber(num);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;native&amp;lt;/tt&amp;gt; keyword tells the compiler that this function exists in an outside source.  The comment style is similar to [http://www.stack.nl/~dimitri/doxygen/ doxygen] or [http://java.sun.com/j2se/javadoc/ Javadoc], and is preferred by the SourceMod Development Team.&lt;br /&gt;
&lt;br /&gt;
==Implementing==&lt;br /&gt;
Now that our function is documented, it's time to create it!  Each native function is bound to a C++ function.  The prototype for this function looks like:&lt;br /&gt;
&amp;lt;cpp&amp;gt;cell_t Function(IPluginContext *pContext, const cell_t *params);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A quick explanation of these types:&lt;br /&gt;
*&amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt; - This is a 32bit signed integer, the generic data type for Pawn.&lt;br /&gt;
*&amp;lt;tt&amp;gt;IPluginContext&amp;lt;/tt&amp;gt; - This interface provides Virtual Machine functions for retrieving or modifying memory in the plugin.&lt;br /&gt;
*&amp;lt;tt&amp;gt;params&amp;lt;/tt&amp;gt; - This is the &amp;quot;stack&amp;quot; of parameters that the plugin passed.  It is an array from [0..N] where 0 contains N. This means &amp;lt;tt&amp;gt;params[0]&amp;lt;/tt&amp;gt; contains the number of arguments passed to the native.&lt;br /&gt;
**For example, if one parameter was passed, and the parameter is 25:&lt;br /&gt;
***&amp;lt;tt&amp;gt;params[0]&amp;lt;/tt&amp;gt; == 1&lt;br /&gt;
***&amp;lt;tt&amp;gt;params[1]&amp;lt;/tt&amp;gt; == 25&lt;br /&gt;
**Even though it tells you how many parameters are passed, you do not need to verify this number.  The compiler will always pass the correct number of parameters in.  The only time you need to verify it is for backwards compatibility or variable parameter lists, which will be discussed later.&lt;br /&gt;
&lt;br /&gt;
Now, let's write our native function:&lt;br /&gt;
&amp;lt;cpp&amp;gt;cell_t SquareNumber(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	cell_t number = params[1];&lt;br /&gt;
	return number * number;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Binding==&lt;br /&gt;
Now, the final step is to bind our native.  Natives are bound in ''native lists''.  Each list must be terminated by a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; bind.  Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;const sp_nativeinfo_t MyNatives[] = &lt;br /&gt;
{&lt;br /&gt;
	{&amp;quot;SquareNumber&amp;quot;,	SquareNumber},&lt;br /&gt;
	{NULL,			NULL},&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first column/member is a string containing the name you've assigned to the native.  The second column/member is the C++ function you're binding to.  Here, both contain the same name, but it is certainly possible to bind a function to any valid Pawn function name, and likewise, you can bind one function to more than one name.&lt;br /&gt;
&lt;br /&gt;
Lastly, you must tell Core about your native list.  There are two places that are good to do this.  Whichever you choose, you must uncomment the function in &amp;lt;tt&amp;gt;extension.h&amp;lt;/tt&amp;gt; and implement it in &amp;lt;tt&amp;gt;extension.cpp&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SDK_OnLoad&amp;lt;/tt&amp;gt; - This is called when your extension is first loaded.  If you do not require any outside interfaces, it is safe to add natives here.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SDK_OnAllLoaded&amp;lt;/tt&amp;gt; - This is called when all extensions have been loaded.  This is generally a better place to add natives.&lt;br /&gt;
&lt;br /&gt;
Let's say we choose &amp;lt;tt&amp;gt;SDK_OnAllLoaded&amp;lt;/tt&amp;gt;, we'd then have code like this:&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Sample::SDK_OnAllLoaded()&lt;br /&gt;
{&lt;br /&gt;
	sharesys-&amp;gt;AddNatives(myself, MyNatives);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
''Note: &amp;lt;tt&amp;gt;myself&amp;lt;/tt&amp;gt; is a global variable declared in the SDK.  It is a pointer that identifies your extension.''&lt;br /&gt;
&lt;br /&gt;
For more information on writing natives, see [[Natives (SourceMod Development)]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Creating Events/Forwards=&lt;br /&gt;
Events are an integral part to SourceMod.  An Event is formally called a ''Forward''.  Forwards are functions inside a plugin which are not called by the plugin itself, but are triggered from an external source.  For example, &amp;lt;tt&amp;gt;OnClientConnect&amp;lt;/tt&amp;gt; is a forward which is triggered when a player connects to a server.&lt;br /&gt;
&lt;br /&gt;
There are two major types of forwards:&lt;br /&gt;
*'''Managed''': This forward is global and has a name.  To use this forward, the function must be declared as &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt; inside the user's script.  Any plugin having this public function will receive the event.&lt;br /&gt;
*'''Unmanaged''': This forward is private in nature.  For example, the &amp;lt;tt&amp;gt;HookUserMessage&amp;lt;/tt&amp;gt; native lets users specify a function to be called when a specific user message is sent.  This is done with an unmanaged forward, and adding functions to this forward is not automatic.  In general, function calls for unmanaged forwards are not public, although they can be.&lt;br /&gt;
&lt;br /&gt;
''Note: To enable the Forward interface, you must uncomment the definition &amp;lt;tt&amp;gt;SMEXT_ENABLE_FORWARDSYS&amp;lt;/tt&amp;gt; in smsdk_config.h.''&lt;br /&gt;
==Managed Forwards==&lt;br /&gt;
Let's say we want to create a forward that will be called when a player uses say chat.  For simplicity, let's assume you already have a function that tells you when a player says say chat.  We will just be creating the forward for it.&lt;br /&gt;
&lt;br /&gt;
As we did before, first let's prototype our global forward.  In our include file, we add this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * @brief Called whenever a client says something in chat.&lt;br /&gt;
 *&lt;br /&gt;
 * @param client	Index of the client.&lt;br /&gt;
 * @param text		String containing the say text.&lt;br /&gt;
 * @return 		Plugin_Handled to block text from printing, Plugin_Continue otherwise.&lt;br /&gt;
 */&lt;br /&gt;
forward Action OnPlayerSayChat(int client, const char[] text);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;forward&amp;lt;/tt&amp;gt; keyword tells the compiler that any function having this name must be declared exactly the same.  In a plugin, this would&lt;br /&gt;
&lt;br /&gt;
The next step is to declare your forward somewhere at the top of your &amp;lt;tt&amp;gt;extension.cpp&amp;lt;/tt&amp;gt; file.  This will look like:&lt;br /&gt;
&amp;lt;cpp&amp;gt;IForward *g_pSayChat = NULL&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, re-using our code from above, let's create this forward in &amp;lt;tt&amp;gt;SDK_OnAllLoaded&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Sample::SDK_OnAllLoaded()&lt;br /&gt;
{&lt;br /&gt;
	sharesys-&amp;gt;AddNatives(myself, MyNatives);&lt;br /&gt;
	g_pSayChat = forwards-&amp;gt;CreateForward(&amp;quot;OnPlayerSayChat&amp;quot;, ET_Event, 2, NULL, Param_Cell, Param_String);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanation of parameters:&lt;br /&gt;
*&amp;lt;tt&amp;gt;&amp;quot;OnPlayerSayChat&amp;quot;&amp;lt;/tt&amp;gt; - The name of our forward.&lt;br /&gt;
*&amp;lt;tt&amp;gt;ET_Event&amp;lt;/tt&amp;gt; - Since forwards can execute multiple functions in multiple scripts, this is one of the ways of specifying what to do with the return value of each function.  &amp;lt;tt&amp;gt;ET_Event&amp;lt;/tt&amp;gt; means &amp;quot;return the highest value, do not allow stops.&amp;quot;  A stop refers to &amp;lt;tt&amp;gt;Pl_Stop&amp;lt;/tt&amp;gt;, which lets a plugin block the rest of the event chain.&lt;br /&gt;
*&amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; - This is the number of parameters our forward will have.&lt;br /&gt;
*&amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; - Not used in our example.  This lets you pass parameters by array rather than variable arguments.&lt;br /&gt;
*&amp;lt;tt&amp;gt;Param_Cell&amp;lt;/tt&amp;gt; - The first parameter is a cell (integer).&lt;br /&gt;
*&amp;lt;tt&amp;gt;Param_String&amp;lt;/tt&amp;gt; - The second parameter is a string.&lt;br /&gt;
&lt;br /&gt;
Now, we write a quick function in our module to call this forward:&lt;br /&gt;
&amp;lt;cpp&amp;gt;/** Fires the say chat event in plugins.  Returns true to allow the text, false to block. */&lt;br /&gt;
bool FireChatEvent(int client, const char *text)&lt;br /&gt;
{&lt;br /&gt;
	if (!g_pSayChat)&lt;br /&gt;
	{&lt;br /&gt;
		return true;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	cell_t result = 0;&lt;br /&gt;
	g_pSayChat-&amp;gt;PushCell(client);&lt;br /&gt;
	g_pSayChat-&amp;gt;PushString(text);&lt;br /&gt;
	g_pSayChat-&amp;gt;Execute(&amp;amp;result);&lt;br /&gt;
	&lt;br /&gt;
	if (result == Pl_Handled)&lt;br /&gt;
	{&lt;br /&gt;
		return false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return true;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, this was pretty simple.  Each parameter is &amp;quot;pushed&amp;quot; one at a time, in ascending order.  First we push the client index as a cell, then the text as a string.  Once done, we execute, and the value will be returned by reference.&lt;br /&gt;
&lt;br /&gt;
Lastly, there is a caveat.  Unlike natives, SourceMod does not automatically clean up forwards for us when are done.  We have to make sure we destroy them.  Uncomment &amp;lt;tt&amp;gt;SDK_OnUnload&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;extension.h&amp;lt;/tt&amp;gt; and implement it like so:&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Sample::SDK_OnUnload()&lt;br /&gt;
{&lt;br /&gt;
	forwards-&amp;gt;ReleaseForward(g_pSayChat);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Unmanaged Forwards==&lt;br /&gt;
Now things get a bit more complicated.  However, unmanaged forwards are essentially the same -- they just give you more flexibility.  Let's consider the managed example with a new twist.  We want to let users add and remove hooks from their plugins, rather than having one global forward.  The standard way to do this is with ''function IDs''.  &lt;br /&gt;
&lt;br /&gt;
Example prototype:&lt;br /&gt;
&amp;lt;pawn&amp;gt;typedef SayChatHook = function Action (int client, const char[] text);&lt;br /&gt;
&lt;br /&gt;
native void AddSayChatHook(SayChatHook hook);&lt;br /&gt;
native void RemoveSayChatHook(SayChatHook hook);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;funcenum&amp;lt;/tt&amp;gt; syntax lets you define all the valid prototypes for your hook.  In this example, the only valid method is a function declared like this (only MyHook can be changed):&lt;br /&gt;
&amp;lt;pawn&amp;gt;Action MyHook(int client, const char[] text)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How do we make such a beast?  The first step is setting up our forward.&lt;br /&gt;
&amp;lt;cpp&amp;gt;IChangeableForward *g_pSayChat = NULL;&lt;br /&gt;
/* ... */&lt;br /&gt;
void Sample::SDK_OnAllLoaded()&lt;br /&gt;
{&lt;br /&gt;
	g_pSayChat = forwards-&amp;gt;CreateForwardEx(NULL, ET_Hook, 2, NULL, Param_Cell, Param_String); &lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice two big differences.  We now use &amp;lt;tt&amp;gt;IChangeableForward&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;IForward&amp;lt;/tt&amp;gt;, and we use &amp;lt;tt&amp;gt;CreateForwardEx&amp;lt;/tt&amp;gt; instead.  The initial first parameter specifies a name for our forward - we're going to ignore this.&lt;br /&gt;
&lt;br /&gt;
Now, we need to create our natives.  These will be fairly simple:&lt;br /&gt;
&amp;lt;cpp&amp;gt;cell_t AddSayChatHook(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	g_pSayChat-&amp;gt;AddFunction(pContext, static_cast&amp;lt;funcid_t&amp;gt;(params[1]));&lt;br /&gt;
	return 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
cell_t RemoveSayChatHook(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	IPluginFunction *pFunction = pContext-&amp;gt;GetFunctionById(static_cast&amp;lt;funcid_t&amp;gt;(params[1]));&lt;br /&gt;
	g_pSayChat-&amp;gt;RemoveFunction(pFunction);&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
''Note: These natives must be added -- that step is removed here and explained earlier.''&lt;br /&gt;
&lt;br /&gt;
You do not need to worry about a plugin unloading - Core will automatically remove the functions for you.  Since an &amp;lt;tt&amp;gt;IChangeableForward&amp;lt;/tt&amp;gt; is also an &amp;lt;tt&amp;gt;IForward&amp;lt;/tt&amp;gt;, the &amp;lt;tt&amp;gt;FireChatEvent&amp;lt;/tt&amp;gt; function from earlier does not need to change.  We're done!&lt;br /&gt;
&lt;br /&gt;
==Creating Interfaces==&lt;br /&gt;
Do you want your extension to share an interface?  If so, first you should create an ''interface file''.  This file should contain everything your interface needs - this way other authors can easily reference it.  Your interface must inherit the &amp;lt;tt&amp;gt;SMInterface&amp;lt;/tt&amp;gt; class.  It must also declare two global macros that uniquely identify your interface.  It must also implement two functions: &amp;lt;tt&amp;gt;GetInterfaceName&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;GetInterfaceVersion&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The two defines must start with &amp;lt;tt&amp;gt;SMINTERFACE_&amp;lt;/tt&amp;gt; and end with &amp;lt;tt&amp;gt;_NAME&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;_VERSION&amp;lt;/tt&amp;gt; respectively.  The first must be a string and the second must be an unsigned integer.  This integer represents your interface's version number.  While you are free to use it however you please, by default it should be linearly increased.  If you make breaking changes or change the versioning scheme, you must overload the &amp;lt;tt&amp;gt;IsVersionCompat&amp;lt;/tt&amp;gt; function in &amp;lt;tt&amp;gt;SMInterface&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;#ifndef _INCLUDE_MYINTERFACE_FILE_H_&lt;br /&gt;
#define _INCLUDE_MYINTERFACE_FILE_H_&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;IShareSys.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define SMINTERFACE_MYINTERFACE_NAME	&amp;quot;IMyInterface&amp;quot;&lt;br /&gt;
#define SMINTERFACE_MYINTERFACE_VERSION	1&lt;br /&gt;
&lt;br /&gt;
class IMyInterface : public SourceMod::SMInterface&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
	virtual const char *GetInterfaceName()&lt;br /&gt;
	{&lt;br /&gt;
		return SMINTERFACE_MYINTERFACE_NAME;&lt;br /&gt;
	}&lt;br /&gt;
	virtual unsigned int GetInterfaceVersion()&lt;br /&gt;
	{&lt;br /&gt;
		return SMINTERFACE_MYINTERFACE_VERSION;&lt;br /&gt;
	}&lt;br /&gt;
public:&lt;br /&gt;
	/**&lt;br /&gt;
	 * @brief This function does nothing.&lt;br /&gt;
	 */&lt;br /&gt;
	virtual void DoNothingAtAll() =0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#endif //_INCLUDE_MYINTERFACE_FILE_H_&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice, of course, that our interface is ''pure virtual''.  This means it must be implemented in the extension.  Assuming you know C++, this should be fairly straight forward, so let's skip right to how to add this interface to the SourceMod shared system:&lt;br /&gt;
&amp;lt;cpp&amp;gt;bool Sample::SDK_OnLoad(char *error, size_t err_max, bool late)&lt;br /&gt;
{&lt;br /&gt;
	sharesys-&amp;gt;AddInterface(myself, &amp;amp;g_MyInterface);&lt;br /&gt;
	return true;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
''Note: We do this in &amp;lt;tt&amp;gt;SDK_OnLoad()&amp;lt;/tT&amp;gt; instead of &amp;lt;tt&amp;gt;SDK_OnAllLoaded()&amp;lt;/tt&amp;gt;.  Otherwise, an extension might try to search for your interface during &amp;lt;tt&amp;gt;SDK_OnAllLoaded()&amp;lt;/tt&amp;gt;, and it might fail depending on the load order.''&lt;br /&gt;
&lt;br /&gt;
That simple?  Yup!  Now other extensions can use your interface.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Using Interfaces/Other Extensions=&lt;br /&gt;
There are a variety of interfaces that are available, but not loaded by default in the Extension SDK.  These interfaces can be retrieved and used in your extension.&lt;br /&gt;
&lt;br /&gt;
==Core Interfaces==&lt;br /&gt;
If they are provided by Core, getting them is very simple.  Many interfaces can simply be uncommented in &amp;lt;tt&amp;gt;smsdk_config.h&amp;lt;/tt&amp;gt; and they will become usable.  See the &amp;quot;Available Interfaces&amp;quot; list below for the exposure list.&lt;br /&gt;
&lt;br /&gt;
Otherwise, most of the &amp;lt;tt&amp;gt;.h&amp;lt;/tt&amp;gt; interface files in the root of the &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt; folder in the SDK are Core interfaces.  For example, code to use the IPluginManager interface might look like this:&lt;br /&gt;
&amp;lt;cpp&amp;gt;#include &amp;lt;IPluginSys.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
IPluginManager *g_pPlugins = NULL;&lt;br /&gt;
&lt;br /&gt;
bool Sample::SDK_OnLoad(char *error, size_t err_max, bool late)&lt;br /&gt;
{&lt;br /&gt;
	SM_GET_IFACE(PLUGINSYSTEM, g_pPlugins);&lt;br /&gt;
	return true;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where did we get &amp;lt;tt&amp;gt;PLUGINSYSTEM&amp;lt;/tt&amp;gt; from?  Observe the two lines in &amp;lt;tt&amp;gt;IPluginSys.h&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;cpp&amp;gt;#define SMINTERFACE_PLUGINSYSTEM_NAME		&amp;quot;IPluginManager&amp;quot;&lt;br /&gt;
#define SMINTERFACE_PLUGINSYSTEM_VERSION	1&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;SM_GET_IFACE&amp;lt;/tt&amp;gt; macro uses the text in between the &amp;lt;tt&amp;gt;SMINTERFACE_&amp;lt;/tt&amp;gt; and the &amp;lt;tt&amp;gt;_NAME&amp;lt;/tt&amp;gt; characters.  It also uses the version for compatibility checking.  If it can't find the interface, it automatically prints to the error buffer and returns false.&lt;br /&gt;
&lt;br /&gt;
===Default Interfaces===&lt;br /&gt;
There are interfaces which are grabbed by the Extension SDK by default.  You do not need to query for them on load, or even check if they are valid or not.  They are:&lt;br /&gt;
*&amp;lt;tt&amp;gt;IShareSys&amp;lt;/tt&amp;gt; - Exposed as &amp;lt;tt&amp;gt;sharesys&amp;lt;/tt&amp;gt;, found in &amp;lt;tt&amp;gt;IShareSys.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;HANDLESYSTEM&amp;lt;/tt&amp;gt; - Exposed as &amp;lt;tt&amp;gt;handlesys&amp;lt;/tt&amp;gt;, found in &amp;lt;tt&amp;gt;IHandleSys.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SOURCEMOD&amp;lt;/tt&amp;gt; - Exposed as &amp;lt;tt&amp;gt;g_pSM&amp;lt;/tt&amp;gt;, found in &amp;lt;tt&amp;gt;ISourceMod.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;FORWARDMANAGER&amp;lt;/tt&amp;gt; - Exposed as &amp;lt;tt&amp;gt;forwards&amp;lt;/tt&amp;gt;, found in &amp;lt;tt&amp;gt;IForwardSys.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Available Interfaces===&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_FORWARDSYS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;forwards&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_HANDLESYS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;handlesys&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_PLAYERHELPERS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;playerhelpers&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_DBMANAGER&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;dbi&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_GAMECONF&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;gameconfs&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_MEMUTILS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;memutils&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_GAMEHELPERS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;gamehelpers&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_TIMERSYS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;timersys&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_THREADER&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;threader&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==External Interfaces==&lt;br /&gt;
The situation changes if your extension requires ''another extension'', since extensions may load in a completely random order.  The first step is to mark the other extension as a dependency.  Let's say you want to use the &amp;lt;tt&amp;gt;IThreader.h&amp;lt;/tt&amp;gt; interfaces from &amp;lt;tt&amp;gt;threader.ext.dll&amp;lt;/tt&amp;gt;.  First, we declare it as such:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;bool Sample::SDK_OnLoad(char *error, size_t err_max, bool late)&lt;br /&gt;
{&lt;br /&gt;
	sharesys-&amp;gt;AddDependency(myself, &amp;quot;thread.ext&amp;quot;, true, true);&lt;br /&gt;
	return true;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two boolean parameters to &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt; mean, respectively: &amp;quot;try to automatically load this extension&amp;quot; and &amp;quot;this extension cannot work without the dependency.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Second, we query for the interface in &amp;lt;tt&amp;gt;SDK_OnAllLoaded&amp;lt;/tt&amp;gt;.  Since we don't know when &amp;lt;tt&amp;gt;thread.ext&amp;lt;/tt&amp;gt; will actually be loaded, we have to wait until everything is definitely loaded.&lt;br /&gt;
&amp;lt;cpp&amp;gt;IThreader *g_pThreader = NULL;&lt;br /&gt;
/* ... */&lt;br /&gt;
void Sample::SDK_OnAllLoaded()&lt;br /&gt;
{&lt;br /&gt;
	SM_GET_LATE_IFACE(THREADER, g_pThreader);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Third, we need to find a way to fail if this interface was never found.  The way to do this is by uncommenting &amp;lt;tt&amp;gt;QueryRunning&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;extension.h&amp;lt;/tt&amp;gt; and implementing it:&lt;br /&gt;
&amp;lt;cpp&amp;gt;bool Sample::QueryRunning(char *error, size_t err_max)&lt;br /&gt;
{&lt;br /&gt;
	SM_CHECK_IFACE(THREADER, g_pThreader);&lt;br /&gt;
	return true;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When SourceMod queries your extension, the macro above will either validate the pointer or return false.  If it returns false, SourceMod marks your extension as failed.&lt;br /&gt;
&lt;br /&gt;
==Caveats==&lt;br /&gt;
===NULL Interfaces===&lt;br /&gt;
There are a few ways that external interfaces can make your code complicated.  The first is simple but a common oversight.  Don't assume interfaces will be okay.  For example, say we want to create a thread once we get the &amp;lt;tt&amp;gt;IThreader&amp;lt;/tt&amp;gt; interface.  Our code should something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Sample::SDK_OnAllLoaded()&lt;br /&gt;
{&lt;br /&gt;
	SM_GET_IFACE(THREADER, g_pThreader);&lt;br /&gt;
	&lt;br /&gt;
	if (QueryRunning(NULL, 0))&lt;br /&gt;
	{&lt;br /&gt;
		g_pThreader-&amp;gt;MakeThread(/* stuff */);&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that we ''query ourself'' in order to find if it's safe to continue executing code.  We could also have simply checked if &amp;lt;tt&amp;gt;g_pThreader&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;, but self-querying has a bonus: if your extension continues to do things like hook events or add listeners, you will be preventing your extension from entirely initializing itself while one interface is bad.  Always make sure you have sanity checks like this where needed.&lt;br /&gt;
&lt;br /&gt;
===Dynamic Unloading===&lt;br /&gt;
The second major caveat is that extensions can be dynamically unloaded.  If you specified yourself as having a dependency and that each dependency is required, you will have no problem.  Your extension will be unloaded before the interface is removed, and you can clean up memory/hooks in your &amp;lt;tt&amp;gt;SDK_OnUnload()&amp;lt;/tt&amp;gt; code.  There are two situations where this is a different story.&lt;br /&gt;
&lt;br /&gt;
====Optional Interfaces====&lt;br /&gt;
The first situation is if you are not requiring an extension that contains an interface.  Now, when the extension unloads, your extension will not be unloaded first.  This creates a small problem, as you must clean up without being unloaded.  There are two functions you can implement in your extension class to resolve this, both documented in &amp;lt;tt&amp;gt;IExtensionSys.h&amp;lt;/tt&amp;gt;:&lt;br /&gt;
*&amp;lt;tt&amp;gt;QueryInterfaceDrop&amp;lt;/tt&amp;gt; - Allows you to request unloading when a specific interface is unloaded.  This is the default behavior for all interfaces.  If you want to block this functionality, continue reading.&lt;br /&gt;
*&amp;lt;tt&amp;gt;NotifyInterfaceDrop&amp;lt;/tt&amp;gt; - This is called when an interface is dropped.  If your plugin will not be unloaded, you can use this to clean up any resources on a specific interface being removed.&lt;br /&gt;
&lt;br /&gt;
====Circular Dependencies====&lt;br /&gt;
The second situation is a bit more complicated.  It is possible for two extensions to have circular dependencies.  For example:&lt;br /&gt;
*Extension &amp;quot;A&amp;quot; requires extension &amp;quot;B.&amp;quot;&lt;br /&gt;
*Extension &amp;quot;B&amp;quot; requires extension &amp;quot;A.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If either extension is unloaded, the opposite extension is unloaded normally.  The first extension then receives the interface drop callbacks.  In this situation, it is essential that the &amp;lt;tt&amp;gt;NotifyInterfaceDrop&amp;lt;/tt&amp;gt; function be implemented and used with the circular interface.  Otherwise, you risk crashing when your extension unloads (or at the very least, leaking memory).  Since the actual drop order is undefined, it means both extensions must implement this function to be safe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Automatic Loading=&lt;br /&gt;
There are two types of automatic loading: Dynamic and Global.  Dynamic loading means your extension is only loaded when a plugin requires it.  Global loading means your extension loads no matter what.&lt;br /&gt;
&lt;br /&gt;
==Dynamic Autoloading==&lt;br /&gt;
Dynamic loading requires that you create an include file for plugins.  Plugins that include your file will automatically load your extension.  This requires implementing the &amp;lt;tt&amp;gt;Extension&amp;lt;/tt&amp;gt; structure found in &amp;lt;tt&amp;gt;core.inc&amp;lt;/tt&amp;gt;.  You must expose the structure as &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt;, and the name must start with &amp;quot;&amp;lt;tt&amp;gt;__ext_&amp;lt;/tt&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Do not edit below this line!&lt;br /&gt;
 */&lt;br /&gt;
public Extension:__ext_geoip = &lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;GeoIP&amp;quot;,&lt;br /&gt;
	file = &amp;quot;geoip.ext&amp;quot;,&lt;br /&gt;
#if defined AUTOLOAD_EXTENSIONS&lt;br /&gt;
	autoload = 1,&lt;br /&gt;
#else&lt;br /&gt;
	autoload = 0,&lt;br /&gt;
#endif&lt;br /&gt;
#if defined REQUIRE_EXTENSIONS&lt;br /&gt;
	required = 1,&lt;br /&gt;
#else&lt;br /&gt;
	required = 0,&lt;br /&gt;
#endif&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
*&amp;lt;b&amp;gt;name&amp;lt;/b&amp;gt;: The name of your module as written in &amp;lt;tt&amp;gt;SMEXT_CONF_NAME&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;b&amp;gt;file&amp;lt;/b&amp;gt;: The platform-inspecific portion of your extension's file name.&lt;br /&gt;
*&amp;lt;b&amp;gt;autoload&amp;lt;/b&amp;gt;: Specifies that your module should always dynamically autoload by default.  You can tweak this to either never autoload or always autoload (without letting the user toggle).&lt;br /&gt;
*&amp;lt;b&amp;gt;required&amp;lt;/b&amp;gt;: Specifies whether or not this extension is '''required''' by your plugin.  If for some reason your extension fails to load (or is not found), the plugin will also fail to load.  This is changeable if you wish to override the default behavior.&lt;br /&gt;
&lt;br /&gt;
You can copy and paste this example, but remember to modify the following portions:&lt;br /&gt;
*&amp;lt;b&amp;gt;__ext_geoip&amp;lt;/b&amp;gt;: Change the &amp;quot;geoip&amp;quot; portion to your own unique variable name.&lt;br /&gt;
*&amp;lt;b&amp;gt;&amp;quot;GeoIP&amp;lt;/b&amp;gt;: Change the GeoIP portion to your extension's name.  This should match the name you chose as &amp;lt;tt&amp;gt;SMEXT_CONF_NAME&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;b&amp;gt;&amp;quot;geoip.ext&amp;quot;&amp;lt;/b&amp;gt;: Change this to your extension's file name, without the .dll/.so portion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Global Autoloading==&lt;br /&gt;
To have your extension always autoload, you must create a ''.autoload'' file in the &amp;lt;tt&amp;gt;extensions&amp;lt;/tt&amp;gt; folder.  For example, to have the &amp;lt;tt&amp;gt;threader.ext.dll&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;threader.ext.so&amp;lt;/tt&amp;gt; extensions autoload, you'd create the following file in &amp;lt;tt&amp;gt;extensions&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;threader.autoload&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few notes:&lt;br /&gt;
*This only works for extensions using the .ext.&amp;lt;platform&amp;gt; convention.  SourceMod cuts off the &amp;quot;.autoload&amp;quot; portion of the file, then adds the appropriate extension just as if 'sm exts load' was used.&lt;br /&gt;
*The file does not need to contain anything, it simply needs to exist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Conventions=&lt;br /&gt;
&lt;br /&gt;
==Designing API/Natives==&lt;br /&gt;
*Start interface names with the capital letter 'I'.&lt;br /&gt;
*Use a consistent naming convention.  SourceMod uses [http://msdn2.microsoft.com/en-us/library/ms229002.aspx Microsoft/Pascal] naming.  Avoid Java/Camel casing for both API and natives.&lt;br /&gt;
*When exposing interfaces, make sure your exposure defines start with &amp;lt;tt&amp;gt;SMINTERFACE_&amp;lt;/tt&amp;gt; and end with &amp;lt;tt&amp;gt;_NAME&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;_VERSION&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==External Naming==&lt;br /&gt;
*Logtags (&amp;lt;tt&amp;gt;SMEXT_CONF_LOGTAG&amp;lt;/tt&amp;gt;) should be short names (under 10 characters or so) in all capital letters.&lt;br /&gt;
*Your extension file name should never have &amp;lt;tt&amp;gt;_i486&amp;lt;/tt&amp;gt; or other unnecessary platform-specific notations in its name.&lt;br /&gt;
*Your extension file name should always end in &amp;lt;tt&amp;gt;.ext.so&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.ext.dll&amp;lt;/tt&amp;gt; depending on the platform.  The &amp;lt;tt&amp;gt;.ext.&amp;lt;/tt&amp;gt; is SourceMod convention.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Setting up Visual Studio=&lt;br /&gt;
&lt;br /&gt;
{{qnotice|It is recommended that you make a copy of the sample_ext project and modify that rather than create your own project, as it will set up most of this for you}}&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sample Project ==&lt;br /&gt;
&lt;br /&gt;
Instead of manually creating a project, you can make a copy of the sample_ext project and modify it.&lt;br /&gt;
&lt;br /&gt;
The sample_ext project assumes that it is located in a subdirectory inside the SourceMod public directory.  To change this, modify all references to ..\.. to $(SOURCEMOD15)\public and specify the SOURCEMOD15 variable as mentioned in the Optional Environment variables.&lt;br /&gt;
&lt;br /&gt;
The sample_ext projectuses the following environment variables to locate the various source code parts.  To set environment variables:&lt;br /&gt;
&lt;br /&gt;
'''Windows XP''': Start -&amp;gt; Settings -&amp;gt; Control Panel -&amp;gt; System -&amp;gt; Advanced -&amp;gt; Environment Variables&lt;br /&gt;
&lt;br /&gt;
'''Windows Vista/7''': Start -&amp;gt; Control Panel -&amp;gt; System -&amp;gt; Advanced system properties -&amp;gt; Advanced -&amp;gt; Environment Variables&lt;br /&gt;
&lt;br /&gt;
=== Environment Variables ===&lt;br /&gt;
&lt;br /&gt;
The environment variables used are:&lt;br /&gt;
&lt;br /&gt;
* '''MMSOURCE17''': Path to MetaMod: Source source code for version 1.7 or newer. Used to compile SourceMod itself.  &lt;br /&gt;
* '''MMSOURCE18''': Path to MetaMod: Source source code for version 1.8 or newer. Used in SourceMod 1.4 projects.  &lt;br /&gt;
* '''MMSOURCE19''': Path to MetaMod: Source source code for version 1.9 or newer. Used in SourceMod 1.5 projects.  &lt;br /&gt;
* '''HL2SDK''': Path to the Episode 1 SDK  &lt;br /&gt;
* '''HL2SDK-SWARM''': Path to the Alien Swarm SDK  &lt;br /&gt;
* '''HL2SDK-DARKM''': Path to the Dark Messiah SDK  &lt;br /&gt;
* '''HL2SDKCSGO''': Path to the Counter-Strike: Global Offensive SDK  &lt;br /&gt;
* '''HL2SDKCSS''': Path to the Counter-Strike: Source SDK  &lt;br /&gt;
* '''HL2SDKL4D''': Path to the Left 4 Dead SDK  &lt;br /&gt;
* '''HL2SDKL4D2''': Path to the Left 4 Dead 2 SDK  &lt;br /&gt;
* '''HL2SDKOB''': Path to the Orange Box SDK (not Source 2009)  &lt;br /&gt;
* '''HL2SDKOBVALVE''': Path to the Orange Box Valve / Source 2009 SDK (Half-Life 2: Deathmatch, Day of Defeat: Source, Team Fortress 2)&lt;br /&gt;
&lt;br /&gt;
Optional environment variables:&lt;br /&gt;
&lt;br /&gt;
* '''SOURCEMOD15'': Optional path to SourceMod 1.5 or newer source code&lt;br /&gt;
&lt;br /&gt;
==Manually configuring a project==&lt;br /&gt;
&lt;br /&gt;
===Paths===&lt;br /&gt;
'''Visual Studio 2003''': Tools -&amp;gt; Options -&amp;gt; Projects, VC++ Directories&lt;br /&gt;
&lt;br /&gt;
'''Visual Studio 2005''': Tools -&amp;gt; Options -&amp;gt; Projects and Solutions -&amp;gt; VC++ Directories&lt;br /&gt;
&lt;br /&gt;
====Include Paths====&lt;br /&gt;
*SourceMod only:&lt;br /&gt;
**sdk\public\extensions&lt;br /&gt;
**sdk\public\sourcepawn&lt;br /&gt;
**sdk\public&lt;br /&gt;
*SourceMM (Note that sourcemm might be 'trunk' for you):&lt;br /&gt;
**sourcemm\core&lt;br /&gt;
**sourcemm\core\sourcehook&lt;br /&gt;
*HL2SDK:&lt;br /&gt;
**game\shared&lt;br /&gt;
**public\vstdlib&lt;br /&gt;
**public\tier1&lt;br /&gt;
**public\tier0&lt;br /&gt;
**public\engine&lt;br /&gt;
**public&lt;br /&gt;
**dlls&lt;br /&gt;
&lt;br /&gt;
====Link Paths====&lt;br /&gt;
*HL2SDK:&lt;br /&gt;
**lib\public for version 2005&lt;br /&gt;
**lib-vc7\public for version 2003&lt;br /&gt;
&lt;br /&gt;
===Compiler Options===&lt;br /&gt;
&amp;lt;b&amp;gt;Note:&amp;lt;/b&amp;gt; These options are set by default in the sample Extension SDK.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Note:&amp;lt;/b&amp;gt; These options should be set for every build (Release/Debug/others).&lt;br /&gt;
&lt;br /&gt;
For VS 2005, goto Project-&amp;gt;Properties.&lt;br /&gt;
&lt;br /&gt;
*General&lt;br /&gt;
**&amp;lt;tt&amp;gt;Character Set&amp;lt;/tt&amp;gt;: '''Use Multi-Byte Character Set'''&lt;br /&gt;
*C/C++&lt;br /&gt;
**General&lt;br /&gt;
***&amp;lt;tt&amp;gt;Detect 64-bit Portability Issues&amp;lt;/tt&amp;gt;: '''No'''&lt;br /&gt;
**Preprocessor&lt;br /&gt;
***&amp;lt;tt&amp;gt;Preprocessor Defines&amp;lt;/tt&amp;gt;: Add &amp;lt;tt&amp;gt;_CRT_SECURE_NO_DEPRECATE&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;_CRT_NONSTDC_NO_DEPRECATE&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SOURCEMOD_BUILD&amp;lt;/tt&amp;gt;  and &amp;lt;tt&amp;gt;WIN32&amp;lt;/tt&amp;gt;&lt;br /&gt;
**Code Generation&lt;br /&gt;
***&amp;lt;tt&amp;gt;Runtime Library&amp;lt;/tt&amp;gt;: Multi-threaded or /MT (for Release), Multi-threaded Debug or /MTd (for Debug)&lt;br /&gt;
*Linker&lt;br /&gt;
**General&lt;br /&gt;
***&amp;lt;tt&amp;gt;Output File&amp;lt;/tt&amp;gt;: Change &amp;lt;tt&amp;gt;$(ProjectName)&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;$(ProjectName).ext&amp;lt;/tt&amp;gt;, or use your own custom string.&lt;br /&gt;
**Input&lt;br /&gt;
***&amp;lt;tt&amp;gt;Additional Dependencies&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;tier0.lib tier1.lib vstdlib.lib&amp;lt;/tt&amp;gt; (for SourceMM attached extensions only)&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod]]&lt;br /&gt;
[[Category:SourceMod Development]]&lt;/div&gt;</summary>
		<author><name>Hmmmmm</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Writing_Extensions&amp;diff=10497</id>
		<title>Writing Extensions</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Writing_Extensions&amp;diff=10497"/>
		<updated>2018-01-01T21:31:48Z</updated>

		<summary type="html">&lt;p&gt;Hmmmmm: Added hl2sdk github link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;SourceMod's Extension System is a powerful way to greatly enhance the flexibility of your SourceMod plugins.  You can take full advantage of SourceMod's Core, using the interfaces it provides, to create C++ plugins, plugin events, plugin native functions, and shared interfaces.  Extensions can also hook into Metamod:Source.&lt;br /&gt;
&lt;br /&gt;
This article goes into the details of creating a SourceMod Extension.  Knowledge of C++ is required.&lt;br /&gt;
&lt;br /&gt;
=SDK Structure=&lt;br /&gt;
First, download the [[SourceMod SDK]] from the [https://github.com/alliedmodders/sourcemod/releases SourceMod github], and one of the SDKs from the [https://github.com/alliedmodders/hl2sdk hl2sdk github]. The directory structure should contain these folders:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
* hl2sdk-something - One of the HL2 SDKs&lt;br /&gt;
* sourcemod-version - The sourcemod package&lt;br /&gt;
** extensions - Sourcemod Extensions code&lt;br /&gt;
*** curl - Source code to the cURL extension&lt;br /&gt;
*** geoip - Source code to the GeoIP extension&lt;br /&gt;
*** mysql - Source code to the MySQL extension&lt;br /&gt;
** plugins - Source code to all of SourceMod's plugins&lt;br /&gt;
*** include - The include files which document plugin API&lt;br /&gt;
** public - Interface files for SourceMod's Core Interfaces&lt;br /&gt;
*** extensions  - Interfaces that are provided by extensions&lt;br /&gt;
*** '''sample_ext''' - The Sample Extension SDK&lt;br /&gt;
**** extension.cpp - Sample C++ plugin&lt;br /&gt;
**** extension.h - Sample C++ header file&lt;br /&gt;
**** Makefile - Sample C++ plugin compiler&lt;br /&gt;
**** smsdk_config.h - Sample C++ plugin settings&lt;br /&gt;
** sourcepawn - The include/interface files for SourcePawn&lt;br /&gt;
*** compiler - The SourcePawn Compiler&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Starting an Extension=&lt;br /&gt;
For simplicity, this article will assume you are using the SDK base files. Navigate to &amp;lt;code&amp;gt;extensions/public/sample_ext&amp;lt;/code&amp;gt;, and ensure that you can compile your code. If using the command line, &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; should do this, if using Visual Studio, see [[#Setting up Visual Studio|Setting up Visual Studio]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The first step of creating your extension is to configure it.  Open the &amp;lt;tt&amp;gt;smsdk_config.h&amp;lt;/tt&amp;gt; file and edit each of the following defines.  Use the information below to guide you.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
*SMEXT_CONF_NAME - The general name for your Extension (should be short).&lt;br /&gt;
*SMEXT_CONF_DESCRIPTION - A short description of what your extension does.&lt;br /&gt;
*SMEXT_CONF_VERSION - A version number string.  By convention, SourceMod uses the four set build number notation, so build 1.2.3.4 means:&lt;br /&gt;
**1 is the &amp;quot;Major&amp;quot; release version.&lt;br /&gt;
**2 is the &amp;quot;Minor&amp;quot; release version.&lt;br /&gt;
**3 is the &amp;quot;Maintenance&amp;quot; or &amp;quot;Revision&amp;quot; version.&lt;br /&gt;
**4 is the &amp;quot;Build,&amp;quot; usually an internal source control number.&lt;br /&gt;
*SMEXT_CONF_AUTHOR - Your name (or whoever/whatever authored the plugin).&lt;br /&gt;
*SMEXT_CONF_URL - The URL/homepage of this extension.&lt;br /&gt;
*SMEXT_CONF_LOGTAG - The logtag your extension will use for SourceMod logging.  By convention, try to keep this under ten characters or so, and to make it all caps.&lt;br /&gt;
*SMEXT_CONF_LICENSE - Right now, the SourceMod Dev Team mandates that 3rd party extensions must be under an Open Source license.  Putting a license abbreviation or very short message here is appropriate.  For more information, see [https://www.sourcemod.net/license.php the SourceMod license].&lt;br /&gt;
*SMEXT_CONF_DATESTRING - You do not need to modify this.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
If your plugin requires using SourceHook or Metamod:Source, uncomment this line:&lt;br /&gt;
&amp;lt;code&amp;gt;#define SMEXT_CONF_METAMOD&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Next, you should change the name of your extension. By convention, your extension's class name should start with a capital letter.&lt;br /&gt;
* First, open &amp;lt;code&amp;gt;extension.h&amp;lt;/code&amp;gt; and change &amp;quot;Sample&amp;quot; in this line:&lt;br /&gt;
&amp;lt;cpp&amp;gt;class Sample : public SDKExtension&amp;lt;/cpp&amp;gt;&lt;br /&gt;
* Next, open &amp;lt;code&amp;gt;extension.cpp&amp;lt;/code&amp;gt; change these two lines:&lt;br /&gt;
&amp;lt;cpp&amp;gt;Sample g_Sample;&lt;br /&gt;
SMEXT_LINK(&amp;amp;g_Sample);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Visual Studio Users==&lt;br /&gt;
Make sure you change the name of your &amp;lt;tt&amp;gt;.dll&amp;lt;/tt&amp;gt; file.  The naming convention for SourceMod extensions is &amp;lt;tt&amp;gt;name.ext.dll&amp;lt;/tt&amp;gt;, where &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt; is a short name for your extension.  You are free to change this, but it is highly recommended that you keep the &amp;lt;tt&amp;gt;.ext.dll&amp;lt;/tt&amp;gt; intact.&lt;br /&gt;
&lt;br /&gt;
You can do this by going to &amp;lt;tt&amp;gt;Project&amp;lt;/tt&amp;gt; -&amp;gt; &amp;lt;tt&amp;gt;Properties&amp;lt;/tt&amp;gt; -&amp;gt; &amp;lt;tt&amp;gt;Configuration Properties&amp;lt;/tt&amp;gt; -&amp;gt; &amp;lt;tt&amp;gt;Linker&amp;lt;/tt&amp;gt; -&amp;gt; &amp;lt;tt&amp;gt;General&amp;lt;/tt&amp;gt;.  Set the &amp;lt;tt&amp;gt;Output File&amp;lt;/tt&amp;gt; option appropriately.&lt;br /&gt;
&lt;br /&gt;
==Linux Users==&lt;br /&gt;
Simply edit the &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; and change the &amp;lt;tt&amp;gt;BINARY&amp;lt;/tt&amp;gt; line near the top.  Make sure you do not add any trailing spaces at the end of the name, or the build won't come out right.&lt;br /&gt;
&lt;br /&gt;
You should now be able to compile a blank extension!&lt;br /&gt;
&lt;br /&gt;
=Creating Native Functions=&lt;br /&gt;
''Main article: [[Natives (SourceMod Development)]]''&lt;br /&gt;
&lt;br /&gt;
Most of the time, an extension exists to add &amp;quot;native functions&amp;quot; to the plugin system.  Native functions are simply the functions that plugins can use in SourceMod.  They are coded in C++ and have a short prototype declaration in an include file.&lt;br /&gt;
&lt;br /&gt;
==Prototyping==&lt;br /&gt;
The first step to creating a native is to &amp;lt;tt&amp;gt;spec it&amp;lt;/tt&amp;gt;, or &amp;lt;tt&amp;gt;prototype&amp;lt;/tt&amp;gt; it.  This is a simple but often time consuming process, but if you get in the habit of it, your documentation will be much better.  Let's first create a very simply native.  Here is a prototype for it, which we will place in &amp;lt;tt&amp;gt;sample.inc&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Returns the square of a number.&lt;br /&gt;
 *&lt;br /&gt;
 * @param num	Number to square.&lt;br /&gt;
 * @return	The square of num.&lt;br /&gt;
 */&lt;br /&gt;
native SquareNumber(num);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;native&amp;lt;/tt&amp;gt; keyword tells the compiler that this function exists in an outside source.  The comment style is similar to [http://www.stack.nl/~dimitri/doxygen/ doxygen] or [http://java.sun.com/j2se/javadoc/ Javadoc], and is preferred by the SourceMod Development Team.&lt;br /&gt;
&lt;br /&gt;
==Implementing==&lt;br /&gt;
Now that our function is documented, it's time to create it!  Each native function is bound to a C++ function.  The prototype for this function looks like:&lt;br /&gt;
&amp;lt;cpp&amp;gt;cell_t Function(IPluginContext *pContext, const cell_t *params);&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A quick explanation of these types:&lt;br /&gt;
*&amp;lt;tt&amp;gt;cell_t&amp;lt;/tt&amp;gt; - This is a 32bit signed integer, the generic data type for Pawn.&lt;br /&gt;
*&amp;lt;tt&amp;gt;IPluginContext&amp;lt;/tt&amp;gt; - This interface provides Virtual Machine functions for retrieving or modifying memory in the plugin.&lt;br /&gt;
*&amp;lt;tt&amp;gt;params&amp;lt;/tt&amp;gt; - This is the &amp;quot;stack&amp;quot; of parameters that the plugin passed.  It is an array from [0..N] where 0 contains N. This means &amp;lt;tt&amp;gt;params[0]&amp;lt;/tt&amp;gt; contains the number of arguments passed to the native.&lt;br /&gt;
**For example, if one parameter was passed, and the parameter is 25:&lt;br /&gt;
***&amp;lt;tt&amp;gt;params[0]&amp;lt;/tt&amp;gt; == 1&lt;br /&gt;
***&amp;lt;tt&amp;gt;params[1]&amp;lt;/tt&amp;gt; == 25&lt;br /&gt;
**Even though it tells you how many parameters are passed, you do not need to verify this number.  The compiler will always pass the correct number of parameters in.  The only time you need to verify it is for backwards compatibility or variable parameter lists, which will be discussed later.&lt;br /&gt;
&lt;br /&gt;
Now, let's write our native function:&lt;br /&gt;
&amp;lt;cpp&amp;gt;cell_t SquareNumber(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	cell_t number = params[1];&lt;br /&gt;
	return number * number;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Binding==&lt;br /&gt;
Now, the final step is to bind our native.  Natives are bound in ''native lists''.  Each list must be terminated by a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; bind.  Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;const sp_nativeinfo_t MyNatives[] = &lt;br /&gt;
{&lt;br /&gt;
	{&amp;quot;SquareNumber&amp;quot;,	SquareNumber},&lt;br /&gt;
	{NULL,			NULL},&lt;br /&gt;
};&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first column/member is a string containing the name you've assigned to the native.  The second column/member is the C++ function you're binding to.  Here, both contain the same name, but it is certainly possible to bind a function to any valid Pawn function name, and likewise, you can bind one function to more than one name.&lt;br /&gt;
&lt;br /&gt;
Lastly, you must tell Core about your native list.  There are two places that are good to do this.  Whichever you choose, you must uncomment the function in &amp;lt;tt&amp;gt;extension.h&amp;lt;/tt&amp;gt; and implement it in &amp;lt;tt&amp;gt;extension.cpp&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SDK_OnLoad&amp;lt;/tt&amp;gt; - This is called when your extension is first loaded.  If you do not require any outside interfaces, it is safe to add natives here.&lt;br /&gt;
*&amp;lt;tt&amp;gt;SDK_OnAllLoaded&amp;lt;/tt&amp;gt; - This is called when all extensions have been loaded.  This is generally a better place to add natives.&lt;br /&gt;
&lt;br /&gt;
Let's say we choose &amp;lt;tt&amp;gt;SDK_OnAllLoaded&amp;lt;/tt&amp;gt;, we'd then have code like this:&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Sample::SDK_OnAllLoaded()&lt;br /&gt;
{&lt;br /&gt;
	sharesys-&amp;gt;AddNatives(myself, MyNatives);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
''Note: &amp;lt;tt&amp;gt;myself&amp;lt;/tt&amp;gt; is a global variable declared in the SDK.  It is a pointer that identifies your extension.''&lt;br /&gt;
&lt;br /&gt;
For more information on writing natives, see [[Natives (SourceMod Development)]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Creating Events/Forwards=&lt;br /&gt;
Events are an integral part to SourceMod.  An Event is formally called a ''Forward''.  Forwards are functions inside a plugin which are not called by the plugin itself, but are triggered from an external source.  For example, &amp;lt;tt&amp;gt;OnClientConnect&amp;lt;/tt&amp;gt; is a forward which is triggered when a player connects to a server.&lt;br /&gt;
&lt;br /&gt;
There are two major types of forwards:&lt;br /&gt;
*'''Managed''': This forward is global and has a name.  To use this forward, the function must be declared as &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt; inside the user's script.  Any plugin having this public function will receive the event.&lt;br /&gt;
*'''Unmanaged''': This forward is private in nature.  For example, the &amp;lt;tt&amp;gt;HookUserMessage&amp;lt;/tt&amp;gt; native lets users specify a function to be called when a specific user message is sent.  This is done with an unmanaged forward, and adding functions to this forward is not automatic.  In general, function calls for unmanaged forwards are not public, although they can be.&lt;br /&gt;
&lt;br /&gt;
''Note: To enable the Forward interface, you must uncomment the definition &amp;lt;tt&amp;gt;SMEXT_ENABLE_FORWARDSYS&amp;lt;/tt&amp;gt; in smsdk_config.h.''&lt;br /&gt;
==Managed Forwards==&lt;br /&gt;
Let's say we want to create a forward that will be called when a player uses say chat.  For simplicity, let's assume you already have a function that tells you when a player says say chat.  We will just be creating the forward for it.&lt;br /&gt;
&lt;br /&gt;
As we did before, first let's prototype our global forward.  In our include file, we add this:&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * @brief Called whenever a client says something in chat.&lt;br /&gt;
 *&lt;br /&gt;
 * @param client	Index of the client.&lt;br /&gt;
 * @param text		String containing the say text.&lt;br /&gt;
 * @return 		Pl_Handled to block text from printing, Pl_Continue otherwise.&lt;br /&gt;
 */&lt;br /&gt;
forward ResultType:OnPlayerSayChat(client, const String:text[]);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;forward&amp;lt;/tt&amp;gt; keyword tells the compiler that any function having this name must be declared exactly the same.  In a plugin, this would&lt;br /&gt;
&lt;br /&gt;
The next step is to declare your forward somewhere at the top of your &amp;lt;tt&amp;gt;extension.cpp&amp;lt;/tt&amp;gt; file.  This will look like:&lt;br /&gt;
&amp;lt;cpp&amp;gt;IForward *g_pSayChat = NULL&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, re-using our code from above, let's create this forward in &amp;lt;tt&amp;gt;SDK_OnAllLoaded&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Sample::SDK_OnAllLoaded()&lt;br /&gt;
{&lt;br /&gt;
	sharesys-&amp;gt;AddNatives(myself, MyNatives);&lt;br /&gt;
	g_pSayChat = forwards-&amp;gt;CreateForward(&amp;quot;OnPlayerSayChat&amp;quot;, ET_Event, 2, NULL, Param_Cell, Param_String);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanation of parameters:&lt;br /&gt;
*&amp;lt;tt&amp;gt;&amp;quot;OnPlayerSayChat&amp;quot;&amp;lt;/tt&amp;gt; - The name of our forward.&lt;br /&gt;
*&amp;lt;tt&amp;gt;ET_Event&amp;lt;/tt&amp;gt; - Since forwards can execute multiple functions in multiple scripts, this is one of the ways of specifying what to do with the return value of each function.  &amp;lt;tt&amp;gt;ET_Event&amp;lt;/tt&amp;gt; means &amp;quot;return the highest value, do not allow stops.&amp;quot;  A stop refers to &amp;lt;tt&amp;gt;Pl_Stop&amp;lt;/tt&amp;gt;, which lets a plugin block the rest of the event chain.&lt;br /&gt;
*&amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt; - This is the number of parameters our forward will have.&lt;br /&gt;
*&amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; - Not used in our example.  This lets you pass parameters by array rather than variable arguments.&lt;br /&gt;
*&amp;lt;tt&amp;gt;Param_Cell&amp;lt;/tt&amp;gt; - The first parameter is a cell (integer).&lt;br /&gt;
*&amp;lt;tt&amp;gt;Param_String&amp;lt;/tt&amp;gt; - The second parameter is a string.&lt;br /&gt;
&lt;br /&gt;
Now, we write a quick function in our module to call this forward:&lt;br /&gt;
&amp;lt;cpp&amp;gt;/** Fires the say chat event in plugins.  Returns true to allow the text, false to block. */&lt;br /&gt;
bool FireChatEvent(int client, const char *text)&lt;br /&gt;
{&lt;br /&gt;
	if (!g_pSayChat)&lt;br /&gt;
	{&lt;br /&gt;
		return true;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	cell_t result = 0;&lt;br /&gt;
	g_pSayChat-&amp;gt;PushCell(client);&lt;br /&gt;
	g_pSayChat-&amp;gt;PushString(text);&lt;br /&gt;
	g_pSayChat-&amp;gt;Execute(&amp;amp;result);&lt;br /&gt;
	&lt;br /&gt;
	if (result == Pl_Handled)&lt;br /&gt;
	{&lt;br /&gt;
		return false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return true;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, this was pretty simple.  Each parameter is &amp;quot;pushed&amp;quot; one at a time, in ascending order.  First we push the client index as a cell, then the text as a string.  Once done, we execute, and the value will be returned by reference.&lt;br /&gt;
&lt;br /&gt;
Lastly, there is a caveat.  Unlike natives, SourceMod does not automatically clean up forwards for us when are done.  We have to make sure we destroy them.  Uncomment &amp;lt;tt&amp;gt;SDK_OnUnload&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;extension.h&amp;lt;/tt&amp;gt; and implement it like so:&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Sample::SDK_OnUnload()&lt;br /&gt;
{&lt;br /&gt;
	forwards-&amp;gt;ReleaseForward(g_pSayChat);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Unmanaged Forwards==&lt;br /&gt;
Now things get a bit more complicated.  However, unmanaged forwards are essentially the same -- they just give you more flexibility.  Let's consider the managed example with a new twist.  We want to let users add and remove hooks from their plugins, rather than having one global forward.  The standard way to do this is with ''function IDs''.  &lt;br /&gt;
&lt;br /&gt;
Example prototype:&lt;br /&gt;
&amp;lt;pawn&amp;gt;funcenum SayChatHook&lt;br /&gt;
{&lt;br /&gt;
	forward(client, const String:text[]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
native AddSayChatHook(SayChatHook:hook);&lt;br /&gt;
native RemoveSayChatHook(SayChatHook:hook);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;funcenum&amp;lt;/tt&amp;gt; syntax lets you define all the valid prototypes for your hook.  In this example, the only valid method is a function declared like this (only MyHook can be changed):&lt;br /&gt;
&amp;lt;pawn&amp;gt;MyHook(client, const String:text[])&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
How do we make such a beast?  The first step is setting up our forward.&lt;br /&gt;
&amp;lt;cpp&amp;gt;IChangeableForward *g_pSayChat = NULL;&lt;br /&gt;
/* ... */&lt;br /&gt;
void Sample::SDK_OnAllLoaded()&lt;br /&gt;
{&lt;br /&gt;
	g_pSayChat = forwards-&amp;gt;CreateForwardEx(NULL, ET_Hook, 2, NULL, Param_Cell, Param_String); &lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice two big differences.  We now use &amp;lt;tt&amp;gt;IChangeableForward&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;IForward&amp;lt;/tt&amp;gt;, and we use &amp;lt;tt&amp;gt;CreateForwardEx&amp;lt;/tt&amp;gt; instead.  The initial first parameter specifies a name for our forward - we're going to ignore this.&lt;br /&gt;
&lt;br /&gt;
Now, we need to create our natives.  These will be fairly simple:&lt;br /&gt;
&amp;lt;cpp&amp;gt;cell_t AddSayChatHook(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	g_pSayChat-&amp;gt;AddFunction(pContext, static_cast&amp;lt;funcid_t&amp;gt;(params[1]));&lt;br /&gt;
	return 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
cell_t RemoveSayChatHook(IPluginContext *pContext, const cell_t *params)&lt;br /&gt;
{&lt;br /&gt;
	IPluginFunction *pFunction = pContext-&amp;gt;GetFunctionById(static_cast&amp;lt;funcid_t&amp;gt;(params[1]));&lt;br /&gt;
	g_pSayChat-&amp;gt;RemoveFunction(pFunction);&lt;br /&gt;
	return 1;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
''Note: These natives must be added -- that step is removed here and explained earlier.''&lt;br /&gt;
&lt;br /&gt;
You do not need to worry about a plugin unloading - Core will automatically remove the functions for you.  Since an &amp;lt;tt&amp;gt;IChangeableForward&amp;lt;/tt&amp;gt; is also an &amp;lt;tt&amp;gt;IForward&amp;lt;/tt&amp;gt;, the &amp;lt;tt&amp;gt;FireChatEvent&amp;lt;/tt&amp;gt; function from earlier does not need to change.  We're done!&lt;br /&gt;
&lt;br /&gt;
==Creating Interfaces==&lt;br /&gt;
Do you want your extension to share an interface?  If so, first you should create an ''interface file''.  This file should contain everything your interface needs - this way other authors can easily reference it.  Your interface must inherit the &amp;lt;tt&amp;gt;SMInterface&amp;lt;/tt&amp;gt; class.  It must also declare two global macros that uniquely identify your interface.  It must also implement two functions: &amp;lt;tt&amp;gt;GetInterfaceName&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;GetInterfaceVersion&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The two defines must start with &amp;lt;tt&amp;gt;SMINTERFACE_&amp;lt;/tt&amp;gt; and end with &amp;lt;tt&amp;gt;_NAME&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;_VERSION&amp;lt;/tt&amp;gt; respectively.  The first must be a string and the second must be an unsigned integer.  This integer represents your interface's version number.  While you are free to use it however you please, by default it should be linearly increased.  If you make breaking changes or change the versioning scheme, you must overload the &amp;lt;tt&amp;gt;IsVersionCompat&amp;lt;/tt&amp;gt; function in &amp;lt;tt&amp;gt;SMInterface&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;cpp&amp;gt;#ifndef _INCLUDE_MYINTERFACE_FILE_H_&lt;br /&gt;
#define _INCLUDE_MYINTERFACE_FILE_H_&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;IShareSys.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define SMINTERFACE_MYINTERFACE_NAME	&amp;quot;IMyInterface&amp;quot;&lt;br /&gt;
#define SMINTERFACE_MYINTERFACE_VERSION	1&lt;br /&gt;
&lt;br /&gt;
class IMyInterface : public SourceMod::SMInterface&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
	virtual const char *GetInterfaceName()&lt;br /&gt;
	{&lt;br /&gt;
		return SMINTERFACE_MYINTERFACE_NAME;&lt;br /&gt;
	}&lt;br /&gt;
	virtual unsigned int GetInterfaceVersion()&lt;br /&gt;
	{&lt;br /&gt;
		return SMINTERFACE_MYINTERFACE_VERSION;&lt;br /&gt;
	}&lt;br /&gt;
public:&lt;br /&gt;
	/**&lt;br /&gt;
	 * @brief This function does nothing.&lt;br /&gt;
	 */&lt;br /&gt;
	virtual void DoNothingAtAll() =0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#endif //_INCLUDE_MYINTERFACE_FILE_H_&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice, of course, that our interface is ''pure virtual''.  This means it must be implemented in the extension.  Assuming you know C++, this should be fairly straight forward, so let's skip right to how to add this interface to the SourceMod shared system:&lt;br /&gt;
&amp;lt;cpp&amp;gt;bool Sample::SDK_OnLoad(char *error, size_t err_max, bool late)&lt;br /&gt;
{&lt;br /&gt;
	sharesys-&amp;gt;AddInterface(myself, &amp;amp;g_MyInterface);&lt;br /&gt;
	return true;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
''Note: We do this in &amp;lt;tt&amp;gt;SDK_OnLoad()&amp;lt;/tT&amp;gt; instead of &amp;lt;tt&amp;gt;SDK_OnAllLoaded()&amp;lt;/tt&amp;gt;.  Otherwise, an extension might try to search for your interface during &amp;lt;tt&amp;gt;SDK_OnAllLoaded()&amp;lt;/tt&amp;gt;, and it might fail depending on the load order.''&lt;br /&gt;
&lt;br /&gt;
That simple?  Yup!  Now other extensions can use your interface.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Using Interfaces/Other Extensions=&lt;br /&gt;
There are a variety of interfaces that are available, but not loaded by default in the Extension SDK.  These interfaces can be retrieved and used in your extension.&lt;br /&gt;
&lt;br /&gt;
==Core Interfaces==&lt;br /&gt;
If they are provided by Core, getting them is very simple.  Many interfaces can simply be uncommented in &amp;lt;tt&amp;gt;smsdk_config.h&amp;lt;/tt&amp;gt; and they will become usable.  See the &amp;quot;Available Interfaces&amp;quot; list below for the exposure list.&lt;br /&gt;
&lt;br /&gt;
Otherwise, most of the &amp;lt;tt&amp;gt;.h&amp;lt;/tt&amp;gt; interface files in the root of the &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt; folder in the SDK are Core interfaces.  For example, code to use the IPluginManager interface might look like this:&lt;br /&gt;
&amp;lt;cpp&amp;gt;#include &amp;lt;IPluginSys.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
IPluginManager *g_pPlugins = NULL;&lt;br /&gt;
&lt;br /&gt;
bool Sample::SDK_OnLoad(char *error, size_t err_max, bool late)&lt;br /&gt;
{&lt;br /&gt;
	SM_GET_IFACE(PLUGINSYSTEM, g_pPlugins);&lt;br /&gt;
	return true;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where did we get &amp;lt;tt&amp;gt;PLUGINSYSTEM&amp;lt;/tt&amp;gt; from?  Observe the two lines in &amp;lt;tt&amp;gt;IPluginSys.h&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;cpp&amp;gt;#define SMINTERFACE_PLUGINSYSTEM_NAME		&amp;quot;IPluginManager&amp;quot;&lt;br /&gt;
#define SMINTERFACE_PLUGINSYSTEM_VERSION	1&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;SM_GET_IFACE&amp;lt;/tt&amp;gt; macro uses the text in between the &amp;lt;tt&amp;gt;SMINTERFACE_&amp;lt;/tt&amp;gt; and the &amp;lt;tt&amp;gt;_NAME&amp;lt;/tt&amp;gt; characters.  It also uses the version for compatibility checking.  If it can't find the interface, it automatically prints to the error buffer and returns false.&lt;br /&gt;
&lt;br /&gt;
===Default Interfaces===&lt;br /&gt;
There are interfaces which are grabbed by the Extension SDK by default.  You do not need to query for them on load, or even check if they are valid or not.  They are:&lt;br /&gt;
*&amp;lt;tt&amp;gt;IShareSys&amp;lt;/tt&amp;gt; - Exposed as &amp;lt;tt&amp;gt;sharesys&amp;lt;/tt&amp;gt;, found in &amp;lt;tt&amp;gt;IShareSys.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;HANDLESYSTEM&amp;lt;/tt&amp;gt; - Exposed as &amp;lt;tt&amp;gt;handlesys&amp;lt;/tt&amp;gt;, found in &amp;lt;tt&amp;gt;IHandleSys.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SOURCEMOD&amp;lt;/tt&amp;gt; - Exposed as &amp;lt;tt&amp;gt;g_pSM&amp;lt;/tt&amp;gt;, found in &amp;lt;tt&amp;gt;ISourceMod.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;FORWARDMANAGER&amp;lt;/tt&amp;gt; - Exposed as &amp;lt;tt&amp;gt;forwards&amp;lt;/tt&amp;gt;, found in &amp;lt;tt&amp;gt;IForwardSys.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Available Interfaces===&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_FORWARDSYS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;forwards&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_HANDLESYS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;handlesys&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_PLAYERHELPERS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;playerhelpers&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_DBMANAGER&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;dbi&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_GAMECONF&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;gameconfs&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_MEMUTILS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;memutils&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_GAMEHELPERS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;gamehelpers&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_TIMERSYS&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;timersys&amp;lt;/tt&amp;gt;&lt;br /&gt;
*&amp;lt;tt&amp;gt;SMEXT_ENABLE_THREADER&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;threader&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==External Interfaces==&lt;br /&gt;
The situation changes if your extension requires ''another extension'', since extensions may load in a completely random order.  The first step is to mark the other extension as a dependency.  Let's say you want to use the &amp;lt;tt&amp;gt;IThreader.h&amp;lt;/tt&amp;gt; interfaces from &amp;lt;tt&amp;gt;threader.ext.dll&amp;lt;/tt&amp;gt;.  First, we declare it as such:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;bool Sample::SDK_OnLoad(char *error, size_t err_max, bool late)&lt;br /&gt;
{&lt;br /&gt;
	sharesys-&amp;gt;AddDependency(myself, &amp;quot;thread.ext&amp;quot;, true, true);&lt;br /&gt;
	return true;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The two boolean parameters to &amp;lt;tt&amp;gt;AddDependency&amp;lt;/tt&amp;gt; mean, respectively: &amp;quot;try to automatically load this extension&amp;quot; and &amp;quot;this extension cannot work without the dependency.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Second, we query for the interface in &amp;lt;tt&amp;gt;SDK_OnAllLoaded&amp;lt;/tt&amp;gt;.  Since we don't know when &amp;lt;tt&amp;gt;thread.ext&amp;lt;/tt&amp;gt; will actually be loaded, we have to wait until everything is definitely loaded.&lt;br /&gt;
&amp;lt;cpp&amp;gt;IThreader *g_pThreader = NULL;&lt;br /&gt;
/* ... */&lt;br /&gt;
void Sample::SDK_OnAllLoaded()&lt;br /&gt;
{&lt;br /&gt;
	SM_GET_LATE_IFACE(THREADER, g_pThreader);&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Third, we need to find a way to fail if this interface was never found.  The way to do this is by uncommenting &amp;lt;tt&amp;gt;QueryRunning&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;extension.h&amp;lt;/tt&amp;gt; and implementing it:&lt;br /&gt;
&amp;lt;cpp&amp;gt;bool Sample::QueryRunning(char *error, size_t err_max)&lt;br /&gt;
{&lt;br /&gt;
	SM_CHECK_IFACE(THREADER, g_pThreader);&lt;br /&gt;
	return true;&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When SourceMod queries your extension, the macro above will either validate the pointer or return false.  If it returns false, SourceMod marks your extension as failed.&lt;br /&gt;
&lt;br /&gt;
==Caveats==&lt;br /&gt;
===NULL Interfaces===&lt;br /&gt;
There are a few ways that external interfaces can make your code complicated.  The first is simple but a common oversight.  Don't assume interfaces will be okay.  For example, say we want to create a thread once we get the &amp;lt;tt&amp;gt;IThreader&amp;lt;/tt&amp;gt; interface.  Our code should something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;cpp&amp;gt;void Sample::SDK_OnAllLoaded()&lt;br /&gt;
{&lt;br /&gt;
	SM_GET_IFACE(THREADER, g_pThreader);&lt;br /&gt;
	&lt;br /&gt;
	if (QueryRunning(NULL, 0))&lt;br /&gt;
	{&lt;br /&gt;
		g_pThreader-&amp;gt;MakeThread(/* stuff */);&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/cpp&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that we ''query ourself'' in order to find if it's safe to continue executing code.  We could also have simply checked if &amp;lt;tt&amp;gt;g_pThreader&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;, but self-querying has a bonus: if your extension continues to do things like hook events or add listeners, you will be preventing your extension from entirely initializing itself while one interface is bad.  Always make sure you have sanity checks like this where needed.&lt;br /&gt;
&lt;br /&gt;
===Dynamic Unloading===&lt;br /&gt;
The second major caveat is that extensions can be dynamically unloaded.  If you specified yourself as having a dependency and that each dependency is required, you will have no problem.  Your extension will be unloaded before the interface is removed, and you can clean up memory/hooks in your &amp;lt;tt&amp;gt;SDK_OnUnload()&amp;lt;/tt&amp;gt; code.  There are two situations where this is a different story.&lt;br /&gt;
&lt;br /&gt;
====Optional Interfaces====&lt;br /&gt;
The first situation is if you are not requiring an extension that contains an interface.  Now, when the extension unloads, your extension will not be unloaded first.  This creates a small problem, as you must clean up without being unloaded.  There are two functions you can implement in your extension class to resolve this, both documented in &amp;lt;tt&amp;gt;IExtensionSys.h&amp;lt;/tt&amp;gt;:&lt;br /&gt;
*&amp;lt;tt&amp;gt;QueryInterfaceDrop&amp;lt;/tt&amp;gt; - Allows you to request unloading when a specific interface is unloaded.  This is the default behavior for all interfaces.  If you want to block this functionality, continue reading.&lt;br /&gt;
*&amp;lt;tt&amp;gt;NotifyInterfaceDrop&amp;lt;/tt&amp;gt; - This is called when an interface is dropped.  If your plugin will not be unloaded, you can use this to clean up any resources on a specific interface being removed.&lt;br /&gt;
&lt;br /&gt;
====Circular Dependencies====&lt;br /&gt;
The second situation is a bit more complicated.  It is possible for two extensions to have circular dependencies.  For example:&lt;br /&gt;
*Extension &amp;quot;A&amp;quot; requires extension &amp;quot;B.&amp;quot;&lt;br /&gt;
*Extension &amp;quot;B&amp;quot; requires extension &amp;quot;A.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
If either extension is unloaded, the opposite extension is unloaded normally.  The first extension then receives the interface drop callbacks.  In this situation, it is essential that the &amp;lt;tt&amp;gt;NotifyInterfaceDrop&amp;lt;/tt&amp;gt; function be implemented and used with the circular interface.  Otherwise, you risk crashing when your extension unloads (or at the very least, leaking memory).  Since the actual drop order is undefined, it means both extensions must implement this function to be safe.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Automatic Loading=&lt;br /&gt;
There are two types of automatic loading: Dynamic and Global.  Dynamic loading means your extension is only loaded when a plugin requires it.  Global loading means your extension loads no matter what.&lt;br /&gt;
&lt;br /&gt;
==Dynamic Autoloading==&lt;br /&gt;
Dynamic loading requires that you create an include file for plugins.  Plugins that include your file will automatically load your extension.  This requires implementing the &amp;lt;tt&amp;gt;Extension&amp;lt;/tt&amp;gt; structure found in &amp;lt;tt&amp;gt;core.inc&amp;lt;/tt&amp;gt;.  You must expose the structure as &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt;, and the name must start with &amp;quot;&amp;lt;tt&amp;gt;__ext_&amp;lt;/tt&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;/**&lt;br /&gt;
 * Do not edit below this line!&lt;br /&gt;
 */&lt;br /&gt;
public Extension:__ext_geoip = &lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;GeoIP&amp;quot;,&lt;br /&gt;
	file = &amp;quot;geoip.ext&amp;quot;,&lt;br /&gt;
#if defined AUTOLOAD_EXTENSIONS&lt;br /&gt;
	autoload = 1,&lt;br /&gt;
#else&lt;br /&gt;
	autoload = 0,&lt;br /&gt;
#endif&lt;br /&gt;
#if defined REQUIRE_EXTENSIONS&lt;br /&gt;
	required = 1,&lt;br /&gt;
#else&lt;br /&gt;
	required = 0,&lt;br /&gt;
#endif&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Explanations:&lt;br /&gt;
*&amp;lt;b&amp;gt;name&amp;lt;/b&amp;gt;: The name of your module as written in &amp;lt;tt&amp;gt;SMEXT_CONF_NAME&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;b&amp;gt;file&amp;lt;/b&amp;gt;: The platform-inspecific portion of your extension's file name.&lt;br /&gt;
*&amp;lt;b&amp;gt;autoload&amp;lt;/b&amp;gt;: Specifies that your module should always dynamically autoload by default.  You can tweak this to either never autoload or always autoload (without letting the user toggle).&lt;br /&gt;
*&amp;lt;b&amp;gt;required&amp;lt;/b&amp;gt;: Specifies whether or not this extension is '''required''' by your plugin.  If for some reason your extension fails to load (or is not found), the plugin will also fail to load.  This is changeable if you wish to override the default behavior.&lt;br /&gt;
&lt;br /&gt;
You can copy and paste this example, but remember to modify the following portions:&lt;br /&gt;
*&amp;lt;b&amp;gt;__ext_geoip&amp;lt;/b&amp;gt;: Change the &amp;quot;geoip&amp;quot; portion to your own unique variable name.&lt;br /&gt;
*&amp;lt;b&amp;gt;&amp;quot;GeoIP&amp;lt;/b&amp;gt;: Change the GeoIP portion to your extension's name.  This should match the name you chose as &amp;lt;tt&amp;gt;SMEXT_CONF_NAME&amp;lt;/tt&amp;gt;.&lt;br /&gt;
*&amp;lt;b&amp;gt;&amp;quot;geoip.ext&amp;quot;&amp;lt;/b&amp;gt;: Change this to your extension's file name, without the .dll/.so portion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Global Autoloading==&lt;br /&gt;
To have your extension always autoload, you must create a ''.autoload'' file in the &amp;lt;tt&amp;gt;extensions&amp;lt;/tt&amp;gt; folder.  For example, to have the &amp;lt;tt&amp;gt;threader.ext.dll&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;threader.ext.so&amp;lt;/tt&amp;gt; extensions autoload, you'd create the following file in &amp;lt;tt&amp;gt;extensions&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;threader.autoload&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A few notes:&lt;br /&gt;
*This only works for extensions using the .ext.&amp;lt;platform&amp;gt; convention.  SourceMod cuts off the &amp;quot;.autoload&amp;quot; portion of the file, then adds the appropriate extension just as if 'sm exts load' was used.&lt;br /&gt;
*The file does not need to contain anything, it simply needs to exist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Conventions=&lt;br /&gt;
&lt;br /&gt;
==Designing API/Natives==&lt;br /&gt;
*Start interface names with the capital letter 'I'.&lt;br /&gt;
*Use a consistent naming convention.  SourceMod uses [http://msdn2.microsoft.com/en-us/library/ms229002.aspx Microsoft/Pascal] naming.  Avoid Java/Camel casing for both API and natives.&lt;br /&gt;
*When exposing interfaces, make sure your exposure defines start with &amp;lt;tt&amp;gt;SMINTERFACE_&amp;lt;/tt&amp;gt; and end with &amp;lt;tt&amp;gt;_NAME&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;_VERSION&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==External Naming==&lt;br /&gt;
*Logtags (&amp;lt;tt&amp;gt;SMEXT_CONF_LOGTAG&amp;lt;/tt&amp;gt;) should be short names (under 10 characters or so) in all capital letters.&lt;br /&gt;
*Your extension file name should never have &amp;lt;tt&amp;gt;_i486&amp;lt;/tt&amp;gt; or other unnecessary platform-specific notations in its name.&lt;br /&gt;
*Your extension file name should always end in &amp;lt;tt&amp;gt;.ext.so&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.ext.dll&amp;lt;/tt&amp;gt; depending on the platform.  The &amp;lt;tt&amp;gt;.ext.&amp;lt;/tt&amp;gt; is SourceMod convention.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Setting up Visual Studio=&lt;br /&gt;
&lt;br /&gt;
{{qnotice|It is recommended that you make a copy of the sample_ext project and modify that rather than create your own project, as it will set up most of this for you}}&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sample Project ==&lt;br /&gt;
&lt;br /&gt;
Instead of manually creating a project, you can make a copy of the sample_ext project and modify it.&lt;br /&gt;
&lt;br /&gt;
The sample_ext project assumes that it is located in a subdirectory inside the SourceMod public directory.  To change this, modify all references to ..\.. to $(SOURCEMOD15)\public and specify the SOURCEMOD15 variable as mentioned in the Optional Environment variables.&lt;br /&gt;
&lt;br /&gt;
The sample_ext projectuses the following environment variables to locate the various source code parts.  To set environment variables:&lt;br /&gt;
&lt;br /&gt;
'''Windows XP''': Start -&amp;gt; Settings -&amp;gt; Control Panel -&amp;gt; System -&amp;gt; Advanced -&amp;gt; Environment Variables&lt;br /&gt;
&lt;br /&gt;
'''Windows Vista/7''': Start -&amp;gt; Control Panel -&amp;gt; System -&amp;gt; Advanced system properties -&amp;gt; Advanced -&amp;gt; Environment Variables&lt;br /&gt;
&lt;br /&gt;
=== Environment Variables ===&lt;br /&gt;
&lt;br /&gt;
The environment variables used are:&lt;br /&gt;
&lt;br /&gt;
* '''MMSOURCE17''': Path to MetaMod: Source source code for version 1.7 or newer. Used to compile SourceMod itself.  &lt;br /&gt;
* '''MMSOURCE18''': Path to MetaMod: Source source code for version 1.8 or newer. Used in SourceMod 1.4 projects.  &lt;br /&gt;
* '''MMSOURCE19''': Path to MetaMod: Source source code for version 1.9 or newer. Used in SourceMod 1.5 projects.  &lt;br /&gt;
* '''HL2SDK''': Path to the Episode 1 SDK  &lt;br /&gt;
* '''HL2SDK-SWARM''': Path to the Alien Swarm SDK  &lt;br /&gt;
* '''HL2SDK-DARKM''': Path to the Dark Messiah SDK  &lt;br /&gt;
* '''HL2SDKCSGO''': Path to the Counter-Strike: Global Offensive SDK  &lt;br /&gt;
* '''HL2SDKCSS''': Path to the Counter-Strike: Source SDK  &lt;br /&gt;
* '''HL2SDKL4D''': Path to the Left 4 Dead SDK  &lt;br /&gt;
* '''HL2SDKL4D2''': Path to the Left 4 Dead 2 SDK  &lt;br /&gt;
* '''HL2SDKOB''': Path to the Orange Box SDK (not Source 2009)  &lt;br /&gt;
* '''HL2SDKOBVALVE''': Path to the Orange Box Valve / Source 2009 SDK (Half-Life 2: Deathmatch, Day of Defeat: Source, Team Fortress 2)&lt;br /&gt;
&lt;br /&gt;
Optional environment variables:&lt;br /&gt;
&lt;br /&gt;
* '''SOURCEMOD15'': Optional path to SourceMod 1.5 or newer source code&lt;br /&gt;
&lt;br /&gt;
==Manually configuring a project==&lt;br /&gt;
&lt;br /&gt;
===Paths===&lt;br /&gt;
'''Visual Studio 2003''': Tools -&amp;gt; Options -&amp;gt; Projects, VC++ Directories&lt;br /&gt;
&lt;br /&gt;
'''Visual Studio 2005''': Tools -&amp;gt; Options -&amp;gt; Projects and Solutions -&amp;gt; VC++ Directories&lt;br /&gt;
&lt;br /&gt;
====Include Paths====&lt;br /&gt;
*SourceMod only:&lt;br /&gt;
**sdk\public\extensions&lt;br /&gt;
**sdk\public\sourcepawn&lt;br /&gt;
**sdk\public&lt;br /&gt;
*SourceMM (Note that sourcemm might be 'trunk' for you):&lt;br /&gt;
**sourcemm\core&lt;br /&gt;
**sourcemm\core\sourcehook&lt;br /&gt;
*HL2SDK:&lt;br /&gt;
**game\shared&lt;br /&gt;
**public\vstdlib&lt;br /&gt;
**public\tier1&lt;br /&gt;
**public\tier0&lt;br /&gt;
**public\engine&lt;br /&gt;
**public&lt;br /&gt;
**dlls&lt;br /&gt;
&lt;br /&gt;
====Link Paths====&lt;br /&gt;
*HL2SDK:&lt;br /&gt;
**lib\public for version 2005&lt;br /&gt;
**lib-vc7\public for version 2003&lt;br /&gt;
&lt;br /&gt;
===Compiler Options===&lt;br /&gt;
&amp;lt;b&amp;gt;Note:&amp;lt;/b&amp;gt; These options are set by default in the sample Extension SDK.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Note:&amp;lt;/b&amp;gt; These options should be set for every build (Release/Debug/others).&lt;br /&gt;
&lt;br /&gt;
For VS 2005, goto Project-&amp;gt;Properties.&lt;br /&gt;
&lt;br /&gt;
*General&lt;br /&gt;
**&amp;lt;tt&amp;gt;Character Set&amp;lt;/tt&amp;gt;: '''Use Multi-Byte Character Set'''&lt;br /&gt;
*C/C++&lt;br /&gt;
**General&lt;br /&gt;
***&amp;lt;tt&amp;gt;Detect 64-bit Portability Issues&amp;lt;/tt&amp;gt;: '''No'''&lt;br /&gt;
**Preprocessor&lt;br /&gt;
***&amp;lt;tt&amp;gt;Preprocessor Defines&amp;lt;/tt&amp;gt;: Add &amp;lt;tt&amp;gt;_CRT_SECURE_NO_DEPRECATE&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;_CRT_NONSTDC_NO_DEPRECATE&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;SOURCEMOD_BUILD&amp;lt;/tt&amp;gt;  and &amp;lt;tt&amp;gt;WIN32&amp;lt;/tt&amp;gt;&lt;br /&gt;
**Code Generation&lt;br /&gt;
***&amp;lt;tt&amp;gt;Runtime Library&amp;lt;/tt&amp;gt;: Multi-threaded or /MT (for Release), Multi-threaded Debug or /MTd (for Debug)&lt;br /&gt;
*Linker&lt;br /&gt;
**General&lt;br /&gt;
***&amp;lt;tt&amp;gt;Output File&amp;lt;/tt&amp;gt;: Change &amp;lt;tt&amp;gt;$(ProjectName)&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;$(ProjectName).ext&amp;lt;/tt&amp;gt;, or use your own custom string.&lt;br /&gt;
**Input&lt;br /&gt;
***&amp;lt;tt&amp;gt;Additional Dependencies&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;tier0.lib tier1.lib vstdlib.lib&amp;lt;/tt&amp;gt; (for SourceMM attached extensions only)&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod]]&lt;br /&gt;
[[Category:SourceMod Development]]&lt;/div&gt;</summary>
		<author><name>Hmmmmm</name></author>
		
	</entry>
</feed>