<?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=Nosoop</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=Nosoop"/>
	<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/Special:Contributions/Nosoop"/>
	<updated>2026-05-09T11:43:07Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.6</generator>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Clients_(SourceMod_Scripting)&amp;diff=11830</id>
		<title>Clients (SourceMod Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Clients_(SourceMod_Scripting)&amp;diff=11830"/>
		<updated>2025-06-02T14:00:44Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: Update documentation to reflect changes in MAXPLAYERS definition&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[SourceMod]] assigns a Client Index number to client in the server. You can use these numbers to refer to specific clients in various SourceMod APIs. In particular, the [Clients APIs https://sm.alliedmods.net/new-api/clients].&lt;br /&gt;
&lt;br /&gt;
The server is given client index 0, and the first connected user will have client index 1.&lt;br /&gt;
&lt;br /&gt;
There are two variables that can be used to talk about the maximum number of clients:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;MaxClients&amp;lt;/tt&amp;gt;: The maximum number of players currently allowed to connect to the server.&lt;br /&gt;
** This is set at runtime based on &amp;lt;tt&amp;gt;gpGlobals-&amp;gt;maxClients&amp;lt;/tt&amp;gt; in the game server.&lt;br /&gt;
* &amp;lt;tt&amp;gt;MAXPLAYERS&amp;lt;/tt&amp;gt;: The theoretical maximum number of clients allowed on any Source game.&lt;br /&gt;
** As of SourceMod 1.12 this number is set to 101 for Team Fortress 2, enough for 100 players + a SourceTV client.&lt;br /&gt;
&lt;br /&gt;
These values represent the '''maximum count of clients'''. Since Client indexing starts at 1, be wary of off-by-one errors here!&lt;br /&gt;
&lt;br /&gt;
It's recommended that you use &amp;lt;tt&amp;gt;&amp;amp;lt;= MaxClients&amp;lt;/tt&amp;gt; when looping through the client list, and &amp;lt;tt&amp;gt;MAXPLAYERS+1&amp;lt;/tt&amp;gt; when initializing an array to contain data for individual clients.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
// Declare static arrays to support the maximum number of clients possible.&lt;br /&gt;
new playerVotes[MAXPLAYERS+1];&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    RegConsoleCmd(&amp;quot;start_vote&amp;quot;, Command_StartVote);&lt;br /&gt;
    RegConsoleCmd(&amp;quot;vote&amp;quot;, Command_Vote);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_StartVote(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
  // Loop through all clients based on current number of max clients.&lt;br /&gt;
  for(int i = 0; i &amp;lt;= MaxClients; i++) {&lt;br /&gt;
    playerVotes[i] = 0;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_Vote(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
    char arg[128];&lt;br /&gt;
    if( args &amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
        GetCmdArg(i, arg, sizeof(arg));&lt;br /&gt;
        // Associate data with clients at their client index in an array.&lt;br /&gt;
        playerVotes[client] = StringToInt(arg);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other notes:&lt;br /&gt;
&lt;br /&gt;
The game engine's CBaseServer has its own &amp;lt;tt&amp;gt;m_clients&amp;lt;/tt&amp;gt; list. You can subtract 1 from a SourceMod client index to get the &amp;lt;tt&amp;gt;CBaseServer::m_clients&amp;lt;/tt&amp;gt; index.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11829</id>
		<title>User:Nosoop/Guide/Advanced</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11829"/>
		<updated>2025-05-23T13:45:19Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section is provided for users that want or need to work with game-specific functionality that SourceMod doesn't provide access to out of the box.&lt;br /&gt;
&lt;br /&gt;
It's assumed that you're comfortable with programming and various terms.  By the end of this page you'll have some knowledge of calling / hooking arbitrary functions in the game.&lt;br /&gt;
&lt;br /&gt;
= What is gamedata? =&lt;br /&gt;
&lt;br /&gt;
''Gamedata'', also known as game data, gameconfig, and gameconf, are files used to specify information tied to a specific game.&lt;br /&gt;
&lt;br /&gt;
As the games that SourceMod runs on are updated independently of SourceMod itself, gamedata is used as a unified way to keep plugins and extensions up to date on game changes without needing to recompile them.&lt;br /&gt;
&lt;br /&gt;
= Finding Functions =&lt;br /&gt;
&lt;br /&gt;
* TODO refer to public SDK if you don't know what you're looking for&lt;br /&gt;
* TODO explain what to do in a game with symbols&lt;br /&gt;
* TODO suggest opening IDA's options and enabling opcode bytes&lt;br /&gt;
* TODO inlined functions&lt;br /&gt;
* TODO debugging&lt;br /&gt;
&lt;br /&gt;
= Finding VTable Offsets =&lt;br /&gt;
&lt;br /&gt;
In C++, a ''virtual method table'' (shorthand &amp;amp;quot;vtable&amp;amp;quot;) is effectively an array of function pointers. It's intended for inheritance — a virtual &amp;lt;code&amp;gt;::DoThing()&amp;lt;/code&amp;gt; method can be different for different classes, and so the code will look up the correct function for a specific instance based on the table for the instance's class. Every class that uses a vtable will hold a reference to it as one of its properties.&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
Once you have the virtual call, jump to its reference in &amp;lt;tt&amp;gt;.rodata&amp;lt;/tt&amp;gt; and make a note of that address.  Scroll up until you see an offset reference (&amp;lt;tt&amp;gt;off_*&amp;lt;/tt&amp;gt; in IDA, &amp;lt;tt&amp;gt;PTR_*&amp;lt;/tt&amp;gt; in Ghidra); that is likely the first entry in the vtable (index 0).  This reference is created by disassemblers as this is the address that is stored in class instances.&lt;br /&gt;
&lt;br /&gt;
Get the difference between your virtual call's address and that of the first entry, then divide by the pointer size (4 on 32-bit platforms, 8 on 64-bit).&lt;br /&gt;
&lt;br /&gt;
For example, given a 32-bit function pointer located at &amp;lt;tt&amp;gt;011AE84Ch&amp;lt;/tt&amp;gt; and the start at &amp;lt;tt&amp;gt;011AE3C8h&amp;lt;/tt&amp;gt;, you do &amp;lt;tt&amp;gt;(0x011AE84C-0x011AE3C8) / 4&amp;lt;/tt&amp;gt;, resulting in the index 289.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if you're familiar with the code or have sources to cross-reference against, you can search for the virtual call itself.  In a Linux disassembly, it will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; get the first vtable by dereferencing the pointer at the start of the class instance&lt;br /&gt;
8B 03       mov  eax, [ebx]&lt;br /&gt;
&lt;br /&gt;
; push the class instance as a parameter&lt;br /&gt;
89 1C 24    mov  [esp], ebx&lt;br /&gt;
&lt;br /&gt;
; call the fourth entry (at index 3) in the vtable: 0xC / sizeof(void*) = 0x3&lt;br /&gt;
FF 50 0C    call dword ptr [eax+0Ch]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If the game isn't stripped of debugging symbols, use [https://asherkin.github.io/vtable/ asherkin's VTable Dumper].  It provides correct offsets for Linux binaries (as it's what it works with), and estimates usually correct offsets for Windows.&lt;br /&gt;
&lt;br /&gt;
There are instances where the dumper isn't correct, so you may need to be careful in those cases.  Known cases include:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/asherkin/vtable/issues/7 Classes that have discontinuous overloaded functions]&lt;br /&gt;
* Possibly multiple inheritance&lt;br /&gt;
&lt;br /&gt;
Aside - the layout of vtables is not the same across platforms.  Notable differences are:&lt;br /&gt;
&lt;br /&gt;
# Linux may have multiple virtual destructors; Windows appears to only have up to one.&lt;br /&gt;
# Linux overloads are in the same order as they are initially defined in the original code.  On Windows, this is the same, except that overloaded functions (those with the same name that accept different parameters) are grouped together and emitted in reverse order.&lt;br /&gt;
&lt;br /&gt;
= Creating Signatures =&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
After you've found a function, you need to tell SourceMod the sequence of bytes unique to it. Those bytes make up a ''signature''.&lt;br /&gt;
&lt;br /&gt;
{{Note|If you're using IDA and only see the mnemonics in the &amp;quot;IDA View&amp;quot; tab, make sure to set the number of opcode bytes in IDA options to a non-zero number.  8 is sufficient in most cases.}}&lt;br /&gt;
&lt;br /&gt;
You could treat just the sequence bytes as the signature directly, but this would break very easily whenever the game is updated. At the machine-code level, the ''instructions'' might be the same for &amp;amp;quot;move X to Y&amp;amp;quot;, but the ''data'' might change — X and Y might be in a different location in the binary altogether. For an example within a longer signature:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; sets esp to the offset aString&lt;br /&gt;
; the bytes 3B B3 25 01 are the absolute offset of aString in this binary in little-endian format (0x0125B33B)&lt;br /&gt;
C7 04 24 3B B3 25 01    mov     dword ptr [esp], offset aString&lt;br /&gt;
&lt;br /&gt;
; call function, the four bytes after E8 are the location of the function&lt;br /&gt;
E8 78 F0 48 00          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
&lt;br /&gt;
; sets eax to arg 0&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The naive signature for that would be &amp;lt;code&amp;gt;\xC7\x04\x24\x3B\xB3\x25\x01\xE8\x78\xF0\x48\x00\x8B\x45\x08&amp;lt;/code&amp;gt;. However, you can't rely on those bytes mentioned to be constant at all:&lt;br /&gt;
&lt;br /&gt;
* The offsets of &amp;lt;code&amp;gt;aString&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UTIL_VarArgs&amp;lt;/code&amp;gt; might be located somewhere else after a game update&lt;br /&gt;
* Relocations may be performed such that the data bytes are different in memory from its on-disk representation&lt;br /&gt;
&lt;br /&gt;
As a solution to this, you use wildcards to mask off the bytes you don't care about. For SourceMod game config files, the sequence &amp;lt;code&amp;gt;\x2A&amp;lt;/code&amp;gt; indicates that particular byte shouldn't be checked and to continue to the next one.&lt;br /&gt;
&lt;br /&gt;
Here is what the previous signature looks like with the masked bytes displayed as &amp;lt;code&amp;gt;??&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
C7 04 24 ?? ?? ?? ??    mov     dword ptr [esp], offset aString&lt;br /&gt;
E8 ?? ?? ?? ??          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A masked signature would then be &amp;lt;code&amp;gt;\xC7\x04\x24\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x45\x08&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Masking is used mainly for offsets, such as for functions and variables. Instructions generally don't change unless the function code itself is modified, at which point you'll want to revisit your binary and update accordingly.&lt;br /&gt;
&lt;br /&gt;
If you're using DHooks with byte signatures (covered later), you may want to also mask out the first six bytes, as a detour will patch in an unconditional JMP at the start to trampoline into a user-defined function, and subsequent scans for the byte signature will fail.&lt;br /&gt;
&lt;br /&gt;
{{Note|This is no longer the case as of SourceMod 1.11, which stores a copy of the original data for scanning purposes.  However, it's noted here for historical / implementation detail reasons.}}&lt;br /&gt;
&lt;br /&gt;
For an extended lesson, you can look at the following material:&lt;br /&gt;
&lt;br /&gt;
* [https://wiki.alliedmods.net/Signature_Scanning Signature Scanning] on the AlliedModders wiki&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If you're using IDA (including Free), use the [https://github.com/alliedmodders/sourcemod/blob/master/tools/ida_scripts/makesig7.idc &amp;lt;code&amp;gt;makesig7.idc&amp;lt;/code&amp;gt;] script. If you're using Ghidra, use [https://github.com/alliedmodders/sourcemod/blob/master/tools/ghidra_scripts/makesig.py &amp;lt;code&amp;gt;makesig.py&amp;lt;/code&amp;gt;].  (Click those filenames to download the respective scripts.)&lt;br /&gt;
&lt;br /&gt;
They generally do pretty well at finding and masking byte signatures, but when it fails or you want a more robust signature, you should understand how to create the signatures manually.&lt;br /&gt;
&lt;br /&gt;
Both scripts may produce different byte signatures for the same function due to using different methods to determine if a given byte should be masked.&lt;br /&gt;
&lt;br /&gt;
It's exceedingly rare, but possible that the binary has two copies of the exact same short function (for example, when they are typechecked and statically casted to different subclasses). Both scripts will fail in that case. SourceMod's signature scanner will use the first match it finds, so if any match is acceptable, you can still use an appropriately masked signature.&lt;br /&gt;
&lt;br /&gt;
If two copies of a function seem to exist, be sure to look at the disassembly to make sure that the functions are indeed the same.&lt;br /&gt;
&lt;br /&gt;
= Finding Addresses =&lt;br /&gt;
&lt;br /&gt;
Sometimes you have a symbol, but you need an address to work with.  That is what the &amp;quot;Addresses&amp;quot; section of a game configuration file is used for.&lt;br /&gt;
&lt;br /&gt;
To find an address, you start from a known location reference (signature).  You may then have to jump to references (that is, dereference locations), then get an offset from the previous reference.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; keys indicate an offset to load / dereference relative to the previous address, and &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; means to shift the previous address without any dereference.  These key / value pairs are processed in the order you specify them in the file; &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; is only valid as the last &amp;quot;operation&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For a C++-like example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// start from an address&lt;br /&gt;
// &amp;quot;FindLocation&amp;quot; would return the location of either a named symbol reference or the start of a byte signature&lt;br /&gt;
uintptr_t addr = FindLocation(&amp;quot;some_signature&amp;quot;);&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr + 40); // gameconf: &amp;quot;read&amp;quot; &amp;quot;40&amp;quot;&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr); // gameconf: &amp;quot;read&amp;quot; &amp;quot;0&amp;quot;&lt;br /&gt;
addr += 13; // gameconf: &amp;quot;offset&amp;quot; &amp;quot;13&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Calling Game Functions =&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== SDKCall Order ==&lt;br /&gt;
&lt;br /&gt;
When performing an {{SourceMod API|file=sdktools|function=SDKCall}}, the parameters need to be passed in the following order:&lt;br /&gt;
&lt;br /&gt;
# The SDKCall handle received from {{SourceMod API|file=sdktools|function=EndPrepSDKCall}}.&lt;br /&gt;
# The &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; instance.  &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; may be omitted in the following cases:&lt;br /&gt;
#* The function was declared as static, where there is no &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; to pass in.&lt;br /&gt;
#* The function was declared with the &amp;lt;tt&amp;gt;SDKCall_GameRules&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SDKCall_EntityList&amp;lt;/tt&amp;gt; call types; SDKTools itself will provide the appropriate global instance.&lt;br /&gt;
# The return buffer, if applicable.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;Vector&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;QAngle&amp;lt;/tt&amp;gt;, the parameter is a &amp;lt;tt&amp;gt;float[3]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt;, the parameters should be a &amp;lt;tt&amp;gt;char[]&amp;lt;/tt&amp;gt; buffer and an &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; specifying the size of the buffer.  The return value of the SDKCall will be the number of characters written, or -1 if the function returned a null pointer (to differentiate between an empty string).&lt;br /&gt;
#* If the function returns a primitive type / entity / edict, it will be the return value of the SDKCall, so no such return buffer is necessary.&lt;br /&gt;
# Any remaining parameters for the function.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// Vector CBaseCombatCharacter::Weapon_ShootPosition() -- has 'this' and 'Vector' return&lt;br /&gt;
float vecShootPosition[3];&lt;br /&gt;
SDKCall(g_hSDKCall, client, vecShootPosition);&lt;br /&gt;
&lt;br /&gt;
// const char *CBaseAnimating::GetSequenceName(int iSequence) -- has 'this', 'char*' return, and parameter&lt;br /&gt;
char sequenceName[64];&lt;br /&gt;
SDKCall(g_hSDKCall, entity, sequenceName, sizeof(sequenceName), iSequence);&lt;br /&gt;
&lt;br /&gt;
// bool CGlobalEntityList::IsEntityPtr(void* pTest) -- SDKCall_EntityList is used, so no 'this' explicitly needed&lt;br /&gt;
// SDKCall passes the return value from the called function as its return value, so use an assignment operator&lt;br /&gt;
Address pTest;&lt;br /&gt;
bool result = SDKCall(g_hSDKCall, pTest);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calling via Signature or Offset? ==&lt;br /&gt;
&lt;br /&gt;
If you have a class with a virtual method, you generally should set up the &amp;lt;tt&amp;gt;SDKCall&amp;lt;/tt&amp;gt; to take a virtual offset.  Doing so allows your plugin to have the expected interactions with other plugin's hooks, covered in the next section.&lt;br /&gt;
&lt;br /&gt;
You should use a signature either when the function is not virtual or if you need to bypass the virtual override on an entity (e.g. calling the parent class's function).  In those instances, only detours will take effect.&lt;br /&gt;
&lt;br /&gt;
= Hooking Game Functions (with DHooks) =&lt;br /&gt;
&lt;br /&gt;
DHooks is an extension bundled with SourceMod that enables plugins to hook functions of their choosing (currently restricted to those accessible via server / engine binaries).  You may use its functionality by including {{SourceMod API|file=dhooks}}.&lt;br /&gt;
&lt;br /&gt;
As with {{SourceMod API|file=sdktools|function=SDKCall}}s, you must ensure that your hook setup is declared with the same parameter and return types to ensure the server continues to operate as you'd expect.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== Virtual Hook or Detour? ==&lt;br /&gt;
&lt;br /&gt;
A virtual hook is mainly used for hooking virtual methods of a class; a detour is used for hooking any function.&lt;br /&gt;
&lt;br /&gt;
While detours can be used to hook the function a virtual table calls into, virtual hooks still have the merit of hooking specific classes / instances.  More specifically:&lt;br /&gt;
&lt;br /&gt;
* DHooks provides the bookkeeping on which instances are and aren't hooked, so for virtual hooks the callback will only be invoked on those you specifically hook.  On detours, you have to filter on instances yourself.&lt;br /&gt;
* On chained inheritance, a virtual hook will only act on the exact class and not any parent nor subclasses, even if they all point to the same virtual function.  Detours will, again, be called on any invocation of the function, including calls to it made by its subclass.&lt;br /&gt;
* On some binaries (especially with more aggressive optimizations in place), multiple function symbols may map to the same place in memory if they output the same code.  As a result, detours may be called when you don't expect them to be.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11828</id>
		<title>User:Nosoop/Guide/Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11828"/>
		<updated>2025-05-08T10:31:51Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Installing the Server */ Add note on Linux listen servers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section assumes that you're starting out with nothing besides a desktop computer, an internet connection, and a drive to program some SourceMod plugins. No programming experience; no problem.&lt;br /&gt;
&lt;br /&gt;
This page will walk you through manually installing the dedicated server software for your desired game, installing SourceMod, and selecting a text editor to use for development.&lt;br /&gt;
&lt;br /&gt;
There are a number of third-party tools that can automate most of these steps, but we'll stick to the first-party approach here to avoid abstractions from breaking under you.&lt;br /&gt;
&lt;br /&gt;
If you are using a third-party tool to manage your server installation, refer to the tool's documentation for their instructions, then skip to [[#Installing SourceMod|Installing SourceMod]] to download the scripting toolchain for your desktop operating system.&lt;br /&gt;
&lt;br /&gt;
= Installing the Server =&lt;br /&gt;
&lt;br /&gt;
{{note|&amp;lt;p&amp;gt;While officially unsupported, SourceMod may be loaded on a Windows game client (the game you launch); the server a game client creates is known as a listen server. However, there are many behavioral quirks that can only be reproduced on a listen server, and you likely won't receive any solutions to those issues that aren't &amp;quot;use a dedicated server&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This guide does not provide instructions to load SourceMod on a game client. It's highly recommended to stick to installing SourceMod on dedicated game server instances to ensure that any plugins you write will have the correct behavior.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Additionally, Linux game clients use stripped server binaries, which are not supported by SourceMod.&amp;lt;/p&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
To install the dedicated server software for the game of your choice, we will use &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt;. If a game server provider (GSP) is hosting the server for you, skip this step as your provider has already provided you with an installation; if you are using a self-hosted game server management panel, refer to the instructions for your software of choice to install your game server in place of this step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is Valve's command-line Steam client. It is used to install and update dedicated game servers.&lt;br /&gt;
&lt;br /&gt;
Refer to [https://developer.valvesoftware.com/wiki/SteamCMD the SteamCMD entry] in the Valve Developer Wiki for download instructions. This varies on the operating system you're running the software on; you can either work on your own desktop or have a hosted (physical or virtual) machine off-premises.&lt;br /&gt;
&lt;br /&gt;
Once &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is extracted, you will need to install a game server. Continue reading the above wiki page to [https://developer.valvesoftware.com/wiki/SteamCMD#Running_SteamCMD run the application], [https://developer.valvesoftware.com/wiki/SteamCMD#SteamCMD_Login sign in (anonymously)], and [https://developer.valvesoftware.com/wiki/SteamCMD#Downloading_an_App download your game server].&lt;br /&gt;
&lt;br /&gt;
You will need the AppID of the game's dedicated server to install it; note that it is different from the game client AppIDs.  See the below table for that and additional related information for some of the supported games.&lt;br /&gt;
&lt;br /&gt;
{{note|Be sure to write down the commands you used when installing the game server!  You will need to issue those commands again whenever the game is updated.}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Dedicated Server Information&lt;br /&gt;
|-&lt;br /&gt;
! Game&lt;br /&gt;
! AppID&lt;br /&gt;
! Mod Directory&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Day of Defeat: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232290&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;dod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Team Fortress 2&lt;br /&gt;
| &amp;lt;code&amp;gt;232250&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;tf&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232330&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;cstrike&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Global Offensive&lt;br /&gt;
| &amp;lt;code&amp;gt;740&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* As of 1.38.5.2 (2023-02-02), servers running under Linux will need to have a relatively modern libstdc++ installed.  [https://www.mail-archive.com/csgo_servers@list.valvesoftware.com/msg14291.html See this mailing list entry for further details.]&lt;br /&gt;
* [[Introduction to SourceMod Plugins#Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported?|See the current state of Counter-Strike 2 here.]]&lt;br /&gt;
* With the release of Counter-Strike 2, CS:GO no longer has first-class Steam support, and the existing Game Coordinator system will not allow players to connect to vanilla installations.  However, the last version of CS:GO is officially available through the Steam &amp;quot;beta&amp;quot; branch system, and is currently supported by SourceMod.  You may use [https://github.com/eldoradoel/NoLobbyReservation the NoLobbyReservation plugin] to allow players to connect.&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead&lt;br /&gt;
| &amp;lt;code&amp;gt;222840&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* This is the one first-party game that requires a [https://www.metamodsource.net/?go=vdf custom VDF file for Metamod:Source].&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2&lt;br /&gt;
| &amp;lt;code&amp;gt;222860&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Half-Life 2: Deathmatch&lt;br /&gt;
| &amp;lt;code&amp;gt;232370&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;hl2mp&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| No More Room in Hell&lt;br /&gt;
| &amp;lt;code&amp;gt;317670&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;nmrih&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Zombie Panic! Source&lt;br /&gt;
| &amp;lt;code&amp;gt;17505&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;zps&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pirates, Vikings &amp;amp; Knights II&lt;br /&gt;
| &amp;lt;code&amp;gt;17575&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;pvkii&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For post-install server configuration, take a look at the [[../Game Server Configuration|Game Server Configuration]] page.&lt;br /&gt;
&lt;br /&gt;
= Installing Metamod:Source =&lt;br /&gt;
&lt;br /&gt;
Before you can install SourceMod on your server, you must first download and install Metamod:Source. Metamod:Source (MM:S) acts as a middleware for different Source Engine games, providing a unified interface for plugins to operate on the game.&lt;br /&gt;
&lt;br /&gt;
SourceMod itself is an MM:S plugin.&lt;br /&gt;
&lt;br /&gt;
# Download [http://www.metamodsource.net/ Metamod:Source]. In most cases, you want a stable release. Use the download package according to your server's operating system.&lt;br /&gt;
#* If the latest download is unavailable, go down the &amp;amp;quot;Latest 20 Builds&amp;amp;quot; until you get to one that is.&lt;br /&gt;
#* Again, make sure you're downloading the correct package for your server; if you're using a hosted instance, it may not be using the same operating system as your personal desktop.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
#* You may need to extract the archive on, or upload the contents to a remote server.&lt;br /&gt;
#** If you are on Windows, the recommended software to use for extracting Linux (&amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt;) archives is [https://www.7-zip.org/download.html 7-zip]; to upload files remotely via FTP, use [https://winscp.net/eng/index.php WinSCP].&lt;br /&gt;
#** If you are using a GSP, refer to their control panel.  Most provide FTP access, and some also allow for uploads directly via browser.&lt;br /&gt;
#** You should verify that the files were transmitted properly to the server; there have been reports of upload failures, zero-length files, and files that were mistakenly sent in text form and corrupted as a result.&lt;br /&gt;
# After installing, you should verify that the installation was successful by starting your server and running &amp;lt;tt&amp;gt;meta version&amp;lt;/tt&amp;gt;.  It should be treated as a known command at this stage.&lt;br /&gt;
#* Most games should work without further configuration, but if you find that MM:S isn't loading, you will want to [https://www.metamodsource.net/?go=vdf generate a custom VDF file].  Known games that require custom VDF files are:&lt;br /&gt;
#** Left 4 Dead 1&lt;br /&gt;
#** Third-party mods using the Source SDK base&lt;br /&gt;
#* Metamod:Source is known to fail to load on CS:GO servers running under Linux by default.  You will want to delete &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to the installation directory, plus read the information in the next bullet point.&lt;br /&gt;
#* If you are using a Linux server you have full control over, read over the [[User:Nosoop/Guide/Game Server Configuration#Platform-specific|Platform-specific setup]] information.&lt;br /&gt;
#* Additional diagnostic information about load failures is available under &amp;lt;tt&amp;gt;metamod-fatal.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Note|On server startup, you may see an error message &amp;lt;tt&amp;gt;Unable to load plugin &amp;quot;addons/metamod/bin/${platform}64/server&amp;quot;&amp;lt;/tt&amp;gt;.  This is normal behavior; the game server will always attempt to load both 32-bit and 64-bit binaries and fail on the one that doesn't match.  If you're sure that you're not running a 64-bit game server instance, you can delete &amp;lt;tt&amp;gt;addons/metamod_x64.vdf&amp;lt;/tt&amp;gt; to only load the 32-bit version, or the other way around.}}&lt;br /&gt;
&lt;br /&gt;
= Installing SourceMod =&lt;br /&gt;
&lt;br /&gt;
The following is mostly lifted from the [[Installing SourceMod]] page.&lt;br /&gt;
&lt;br /&gt;
# Download [https://www.sourcemod.net/ SourceMod]. Same as before; latest available stable release for your server's operating system.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If you plan on creating new plugins, you will also want to download SourceMod for your ''desktop'' operating system and extract the &amp;lt;code&amp;gt;addons/sourcemod/scripting/&amp;lt;/code&amp;gt; folder to a location on your computer.&lt;br /&gt;
&lt;br /&gt;
In the future, you may need to follow [[Upgrading SourceMod|these instructions to upgrade SourceMod]] on your server because of:&lt;br /&gt;
* game updates requiring SourceMod to be rebuilt against a new revision of the Source SDK&lt;br /&gt;
* plugins compiled against newer versions of SourceMod to take advantage of added functionality&lt;br /&gt;
&lt;br /&gt;
= Picking an IDE =&lt;br /&gt;
&lt;br /&gt;
Now that you have the dedicated game server, Metamod:Source, and SourceMod installed, you have most of the tools you need.&lt;br /&gt;
&lt;br /&gt;
If you've never done any programming, you'll need a text editor. It's completely possible to write code in plain old Notepad and invoke the compiler directly, but having a proper development environment makes it much easier to work with code.&lt;br /&gt;
&lt;br /&gt;
The following editors are known to have good support for SourceMod plugins:&lt;br /&gt;
&lt;br /&gt;
* Spider &amp;amp;mdash; recommended when starting out due to it being zero-install; once you are doing more than one-off plugins, move on to one of the non-web text editors&lt;br /&gt;
* Visual Studio Code (VSCode) &amp;amp;mdash; an increasingly popular choice combined with [https://marketplace.visualstudio.com/items?itemName=Sarrus.sourcepawn-vscode Sarrus's VSCode extension] [https://github.com/Sarrus1/sourcepawn-vscode (source code)]&lt;br /&gt;
* BasicPawn&lt;br /&gt;
* Notepad++&lt;br /&gt;
* SPEdit&lt;br /&gt;
* Sublime Text&lt;br /&gt;
&lt;br /&gt;
For more details on each editor and, if necessary, how to set it up for writing SourceMod plugins, look at the [[../Development Environments|Development Environments]] section of the guide.&lt;br /&gt;
&lt;br /&gt;
Once you've settled on a development environment, you can start learning how to create plugins &amp;amp;mdash; head over to the [[../Basics|Basics]] section of the guide to get started.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11825</id>
		<title>User:Nosoop/Guide/Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11825"/>
		<updated>2025-03-02T08:55:40Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Installing the Server */ Add note on CS:GO&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section assumes that you're starting out with nothing besides a desktop computer, an internet connection, and a drive to program some SourceMod plugins. No programming experience; no problem.&lt;br /&gt;
&lt;br /&gt;
This page will walk you through manually installing the dedicated server software for your desired game, installing SourceMod, and selecting a text editor to use for development.&lt;br /&gt;
&lt;br /&gt;
There are a number of third-party tools that can automate most of these steps, but we'll stick to the first-party approach here to avoid abstractions from breaking under you.&lt;br /&gt;
&lt;br /&gt;
If you are using a third-party tool to manage your server installation, refer to the tool's documentation for their instructions, then skip to [[#Installing SourceMod|Installing SourceMod]] to download the scripting toolchain for your desktop operating system.&lt;br /&gt;
&lt;br /&gt;
= Installing the Server =&lt;br /&gt;
&lt;br /&gt;
{{note|&amp;lt;p&amp;gt;While officially unsupported, SourceMod may be loaded on a game client (the game you launch); the server a game client creates is known as a listen server. However, there are many behavioral quirks that can only be reproduced on a listen server, and you likely won't receive any solutions to those issues that aren't &amp;quot;use a dedicated server&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This guide does not provide instructions to load SourceMod on a game client. It's highly recommended to stick to installing SourceMod on dedicated game server instances to ensure that any plugins you write will have the correct behavior.&amp;lt;/p&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
To install the dedicated server software for the game of your choice, we will use &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt;. If a game server provider (GSP) is hosting the server for you, skip this step as your provider has already provided you with an installation; if you are using a self-hosted game server management panel, refer to the instructions for your software of choice to install your game server in place of this step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is Valve's command-line Steam client. It is used to install and update dedicated game servers.&lt;br /&gt;
&lt;br /&gt;
Refer to [https://developer.valvesoftware.com/wiki/SteamCMD the SteamCMD entry] in the Valve Developer Wiki for download instructions. This varies on the operating system you're running the software on; you can either work on your own desktop or have a hosted (physical or virtual) machine off-premises.&lt;br /&gt;
&lt;br /&gt;
Once &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is extracted, you will need to install a game server. Continue reading the above wiki page to [https://developer.valvesoftware.com/wiki/SteamCMD#Running_SteamCMD run the application], [https://developer.valvesoftware.com/wiki/SteamCMD#SteamCMD_Login sign in (anonymously)], and [https://developer.valvesoftware.com/wiki/SteamCMD#Downloading_an_App download your game server].&lt;br /&gt;
&lt;br /&gt;
You will need the AppID of the game's dedicated server to install it; note that it is different from the game client AppIDs.  See the below table for that and additional related information for some of the supported games.&lt;br /&gt;
&lt;br /&gt;
{{note|Be sure to write down the commands you used when installing the game server!  You will need to issue those commands again whenever the game is updated.}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Dedicated Server Information&lt;br /&gt;
|-&lt;br /&gt;
! Game&lt;br /&gt;
! AppID&lt;br /&gt;
! Mod Directory&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Day of Defeat: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232290&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;dod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Team Fortress 2&lt;br /&gt;
| &amp;lt;code&amp;gt;232250&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;tf&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232330&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;cstrike&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Global Offensive&lt;br /&gt;
| &amp;lt;code&amp;gt;740&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* As of 1.38.5.2 (2023-02-02), servers running under Linux will need to have a relatively modern libstdc++ installed.  [https://www.mail-archive.com/csgo_servers@list.valvesoftware.com/msg14291.html See this mailing list entry for further details.]&lt;br /&gt;
* [[Introduction to SourceMod Plugins#Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported?|See the current state of Counter-Strike 2 here.]]&lt;br /&gt;
* With the release of Counter-Strike 2, CS:GO no longer has first-class Steam support, and the existing Game Coordinator system will not allow players to connect to vanilla installations.  However, the last version of CS:GO is officially available through the Steam &amp;quot;beta&amp;quot; branch system, and is currently supported by SourceMod.  You may use [https://github.com/eldoradoel/NoLobbyReservation the NoLobbyReservation plugin] to allow players to connect.&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead&lt;br /&gt;
| &amp;lt;code&amp;gt;222840&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* This is the one first-party game that requires a [https://www.metamodsource.net/?go=vdf custom VDF file for Metamod:Source].&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2&lt;br /&gt;
| &amp;lt;code&amp;gt;222860&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Half-Life 2: Deathmatch&lt;br /&gt;
| &amp;lt;code&amp;gt;232370&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;hl2mp&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| No More Room in Hell&lt;br /&gt;
| &amp;lt;code&amp;gt;317670&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;nmrih&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Zombie Panic! Source&lt;br /&gt;
| &amp;lt;code&amp;gt;17505&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;zps&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pirates, Vikings &amp;amp; Knights II&lt;br /&gt;
| &amp;lt;code&amp;gt;17575&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;pvkii&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For post-install server configuration, take a look at the [[../Game Server Configuration|Game Server Configuration]] page.&lt;br /&gt;
&lt;br /&gt;
= Installing Metamod:Source =&lt;br /&gt;
&lt;br /&gt;
Before you can install SourceMod on your server, you must first download and install Metamod:Source. Metamod:Source (MM:S) acts as a middleware for different Source Engine games, providing a unified interface for plugins to operate on the game.&lt;br /&gt;
&lt;br /&gt;
SourceMod itself is an MM:S plugin.&lt;br /&gt;
&lt;br /&gt;
# Download [http://www.metamodsource.net/ Metamod:Source]. In most cases, you want a stable release. Use the download package according to your server's operating system.&lt;br /&gt;
#* If the latest download is unavailable, go down the &amp;amp;quot;Latest 20 Builds&amp;amp;quot; until you get to one that is.&lt;br /&gt;
#* Again, make sure you're downloading the correct package for your server; if you're using a hosted instance, it may not be using the same operating system as your personal desktop.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
#* You may need to extract the archive on, or upload the contents to a remote server.&lt;br /&gt;
#** If you are on Windows, the recommended software to use for extracting Linux (&amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt;) archives is [https://www.7-zip.org/download.html 7-zip]; to upload files remotely via FTP, use [https://winscp.net/eng/index.php WinSCP].&lt;br /&gt;
#** If you are using a GSP, refer to their control panel.  Most provide FTP access, and some also allow for uploads directly via browser.&lt;br /&gt;
#** You should verify that the files were transmitted properly to the server; there have been reports of upload failures, zero-length files, and files that were mistakenly sent in text form and corrupted as a result.&lt;br /&gt;
# After installing, you should verify that the installation was successful by starting your server and running &amp;lt;tt&amp;gt;meta version&amp;lt;/tt&amp;gt;.  It should be treated as a known command at this stage.&lt;br /&gt;
#* Most games should work without further configuration, but if you find that MM:S isn't loading, you will want to [https://www.metamodsource.net/?go=vdf generate a custom VDF file].  Known games that require custom VDF files are:&lt;br /&gt;
#** Left 4 Dead 1&lt;br /&gt;
#** Third-party mods using the Source SDK base&lt;br /&gt;
#* Metamod:Source is known to fail to load on CS:GO servers running under Linux by default.  You will want to delete &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to the installation directory, plus read the information in the next bullet point.&lt;br /&gt;
#* If you are using a Linux server you have full control over, read over the [[User:Nosoop/Guide/Game Server Configuration#Platform-specific|Platform-specific setup]] information.&lt;br /&gt;
#* Additional diagnostic information about load failures is available under &amp;lt;tt&amp;gt;metamod-fatal.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Note|On server startup, you may see an error message &amp;lt;tt&amp;gt;Unable to load plugin &amp;quot;addons/metamod/bin/${platform}64/server&amp;quot;&amp;lt;/tt&amp;gt;.  This is normal behavior; the game server will always attempt to load both 32-bit and 64-bit binaries and fail on the one that doesn't match.  If you're sure that you're not running a 64-bit game server instance, you can delete &amp;lt;tt&amp;gt;addons/metamod_x64.vdf&amp;lt;/tt&amp;gt; to only load the 32-bit version, or the other way around.}}&lt;br /&gt;
&lt;br /&gt;
= Installing SourceMod =&lt;br /&gt;
&lt;br /&gt;
The following is mostly lifted from the [[Installing SourceMod]] page.&lt;br /&gt;
&lt;br /&gt;
# Download [https://www.sourcemod.net/ SourceMod]. Same as before; latest available stable release for your server's operating system.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If you plan on creating new plugins, you will also want to download SourceMod for your ''desktop'' operating system and extract the &amp;lt;code&amp;gt;addons/sourcemod/scripting/&amp;lt;/code&amp;gt; folder to a location on your computer.&lt;br /&gt;
&lt;br /&gt;
In the future, you may need to follow [[Upgrading SourceMod|these instructions to upgrade SourceMod]] on your server because of:&lt;br /&gt;
* game updates requiring SourceMod to be rebuilt against a new revision of the Source SDK&lt;br /&gt;
* plugins compiled against newer versions of SourceMod to take advantage of added functionality&lt;br /&gt;
&lt;br /&gt;
= Picking an IDE =&lt;br /&gt;
&lt;br /&gt;
Now that you have the dedicated game server, Metamod:Source, and SourceMod installed, you have most of the tools you need.&lt;br /&gt;
&lt;br /&gt;
If you've never done any programming, you'll need a text editor. It's completely possible to write code in plain old Notepad and invoke the compiler directly, but having a proper development environment makes it much easier to work with code.&lt;br /&gt;
&lt;br /&gt;
The following editors are known to have good support for SourceMod plugins:&lt;br /&gt;
&lt;br /&gt;
* Spider &amp;amp;mdash; recommended when starting out due to it being zero-install; once you are doing more than one-off plugins, move on to one of the non-web text editors&lt;br /&gt;
* Visual Studio Code (VSCode) &amp;amp;mdash; an increasingly popular choice combined with [https://marketplace.visualstudio.com/items?itemName=Sarrus.sourcepawn-vscode Sarrus's VSCode extension] [https://github.com/Sarrus1/sourcepawn-vscode (source code)]&lt;br /&gt;
* BasicPawn&lt;br /&gt;
* Notepad++&lt;br /&gt;
* SPEdit&lt;br /&gt;
* Sublime Text&lt;br /&gt;
&lt;br /&gt;
For more details on each editor and, if necessary, how to set it up for writing SourceMod plugins, look at the [[../Development Environments|Development Environments]] section of the guide.&lt;br /&gt;
&lt;br /&gt;
Once you've settled on a development environment, you can start learning how to create plugins &amp;amp;mdash; head over to the [[../Basics|Basics]] section of the guide to get started.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Installing_Metamod:Source&amp;diff=11726</id>
		<title>Installing Metamod:Source</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Installing_Metamod:Source&amp;diff=11726"/>
		<updated>2024-09-05T14:07:50Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: please stop modifying your gameinfos. god is weeping&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This article will guide you through a [[Metamod:Source]] installation.&lt;br /&gt;
&lt;br /&gt;
=Normal Installation=&lt;br /&gt;
&lt;br /&gt;
''Not applicable for Source 2. See GameInfo section below''&lt;br /&gt;
&lt;br /&gt;
Valve sometimes makes changes in their games that break Metamod:Source between releases.  When this happens, you may need to install a snapshot versions of Metamod:Source.  You can see if this is required on the [[Required Versions (SourceMod)|Required Versions]] page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;[http://www.metamodsource.net/ Download] Metamod:Source.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Extract the package to your game folder.  For example, for Counter-Strike:Source, you would have &amp;lt;code&amp;gt;cstrike/addons/metamod&amp;lt;/code&amp;gt; after extracting.  If you are uploading to FTP, extract the files locally before transferring to your server's game folder.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Restart your server.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Type &amp;quot;meta version&amp;quot; in your server console (or RCon).  You should see a line like: &amp;quot;Loaded As: Valve Server Plugin.&amp;quot;  If you see this, you are done.  If the command is not recognized, see the sections below.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When using a Linux server, you may see the following messages:&lt;br /&gt;
&lt;br /&gt;
* An error indicating that it could not be loaded due to &amp;quot;wrong ELF class: ELFCLASS64&amp;quot;.  If you are using a 32-bit dedicated server installation, this is normal behavior; as long as &amp;lt;code&amp;gt;meta version&amp;lt;/code&amp;gt; is recognized, Metamod:Source is installed.&lt;br /&gt;
* An error indicating that it could not be loaded because &amp;quot;/path/to/server_install/bin/libgcc_s.so.1: version `GCC_7.0.0` not found (required by /some_system_path_to/libstdc++.so.6&amp;quot;.  This is because Valve ships their own copies of those libraries.  As modern systems will have newer versions, you can safely delete the listed file from the server install.  Do not delete the file in the system path (usually &amp;lt;code&amp;gt;lib&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;lib32&amp;lt;/code&amp;gt;).&lt;br /&gt;
* If you are running a 64-bit operating system yourself, you may need to install the system's 32-bit libraries.&lt;br /&gt;
** On Debian / Ubuntu, you can do this with &amp;lt;code&amp;gt;apt install gcc-multilib&amp;lt;/code&amp;gt;.&lt;br /&gt;
* You may find more information about any load failures under a &amp;lt;code&amp;gt;metamod-fatal.log&amp;lt;/code&amp;gt; in metamod's &amp;lt;code&amp;gt;bin&amp;lt;/code&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
==Custom VDF File==&lt;br /&gt;
'''Note: This is normally not needed - Metamod:Source 1.10.0 and later include a &amp;lt;code&amp;gt;metamod.vdf&amp;lt;/code&amp;gt; file for easier installation on most games.'''&lt;br /&gt;
&lt;br /&gt;
You really, really do not need to do this.&lt;br /&gt;
&lt;br /&gt;
Known setups that require this step:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Left 4 Dead 1&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;3rd party mods using the Source SDK Base.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Listen servers (created with the in-game &amp;quot;Create Server&amp;quot; option) for non-english game clients.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are running any of the above, then yes, you probably do need it.  But you probably aren't, so you probably don't, and plenty of people have fallen into the trap of doing these steps unnecessarily and have had to be told otherwise.&lt;br /&gt;
&lt;br /&gt;
So again, if you followed the normal installation process above and &amp;lt;code&amp;gt;meta version&amp;lt;/code&amp;gt; was recognized, ''do not do this''.&lt;br /&gt;
&lt;br /&gt;
Otherwise, if you have trouble getting Metamod:Source to load, [http://www.metamodsource.net/?go=vdf go here] to generate a VDF file specific to your game. This file should be placed into your server's &amp;lt;code&amp;gt;addons&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
=Adjust gameinfo file=&lt;br /&gt;
&lt;br /&gt;
'''Adjusting gameinfo for Source 1 is normally not needed. If you do not understand what this is, do NOT do this unless instructed to. The above instructions are sufficient to install Metamod:Source for 99% of servers. For Source 2, this is, however, the only supported loading method. See [[#Source_2|Source 2]] for more info.'''&lt;br /&gt;
&lt;br /&gt;
==Source 1==&lt;br /&gt;
Metamod:Source 1.4.2 and lower used an older method for loading itself.  The advantage of this method was that Metamod:Source could be loaded before the actual game mod, which gave it a small amount of extra functionality.  This functionality was never used by plugin developers, and Steam updates kept overwriting &amp;lt;code&amp;gt;gameinfo&amp;lt;/code&amp;gt; files, so we switched to a different loading mechanism.&lt;br /&gt;
&lt;br /&gt;
However this loading mechanism may still be desirable if you run into backwards compatibility issues, or you have a plugin which takes advantage of the early-loading mechanism.  If this is your case, here are the &amp;lt;code&amp;gt;gameinfo&amp;lt;/code&amp;gt; directions below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Open the file in the mod folder called &amp;lt;code&amp;gt;gameinfo.txt&amp;lt;/code&amp;gt;. You will see a few lines at the bottom like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SearchPaths&lt;br /&gt;
{&lt;br /&gt;
	Game				|gameinfo_path|. &lt;br /&gt;
	Game				cstrike&lt;br /&gt;
	Game				hl2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Add a line after the &amp;lt;code&amp;gt;{&amp;lt;/code&amp;gt; sign but before all of the &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; entries that looks like this:&amp;lt;pre&amp;gt;GameBin				|gameinfo_path|addons/metamod/bin&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;If you're using Windows, you may need to use a backwards slash (\) instead.&lt;br /&gt;
&amp;lt;li&amp;gt;You're done! To test whether it worked, restart your game server and type &amp;lt;code&amp;gt;meta version&amp;lt;/code&amp;gt; in the server console.  You should see a line that says &amp;lt;code&amp;gt;Loaded as: GameDLL (gameinfo.txt)&amp;lt;/code&amp;gt;.&lt;br /&gt;
If it doesn't recognize the command, the installation probably failed.  If the &amp;lt;code&amp;gt;Loaded as:&amp;lt;/code&amp;gt; line says something else, &amp;lt;code&amp;gt;gameinfo&amp;lt;/code&amp;gt; was probably not modified correctly.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;For more information or documentation, see [[:Category:Metamod:Source Documentation]]&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Source 2==&lt;br /&gt;
Source 2 does not have server plugins, so you will need to load Metamod the old-fashioned way: replacing the server library with Metamod's stub loader.&lt;br /&gt;
&lt;br /&gt;
{{Sad|You will need to redo these changes every time a developer pushes a change that modifies gameinfo.gi}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Open the file in the mod folder called &amp;lt;code&amp;gt;gameinfo.gi&amp;lt;/code&amp;gt;. In CS2 this is &amp;lt;code&amp;gt;csgo/gameinfo.gi&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;li&amp;gt;Note that even though it says &amp;lt;code&amp;gt;DO NOT EDIT THIS FILE DIRECTLY&amp;lt;/code&amp;gt; and advises to edit &amp;lt;code&amp;gt;csgo_core/gameinfo.gi&amp;lt;/code&amp;gt;, editing that file does not correctly load Metamod.&lt;br /&gt;
&amp;lt;li&amp;gt;Look for the &amp;lt;code&amp;gt;SearchPaths&amp;lt;/code&amp;gt; section of code.&lt;br /&gt;
&amp;lt;li&amp;gt;Add a line after the &amp;lt;code&amp;gt;{&amp;lt;/code&amp;gt; sign but before all of the &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; entries that looks like this, replacing &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt; (for CS2) with your game name found in lines beneath it:&lt;br /&gt;
&amp;lt;pre&amp;gt;Game csgo/addons/metamod&amp;lt;/pre&amp;gt;&lt;br /&gt;
{{CommonMistake|Make sure the Metamod entry is the '''first''' in the searchpaths list! This list is ordered and placing it anywhere else will prevent Metamod from loading}}&lt;br /&gt;
&amp;lt;li&amp;gt;Using &amp;lt;code&amp;gt;GameBin&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;Game&amp;lt;/code&amp;gt; does not work.&lt;br /&gt;
&amp;lt;li&amp;gt;In Windows, the backslash is no longer required for paths.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;You're done! To test whether it worked, restart your game server and type &amp;lt;code&amp;gt;meta version&amp;lt;/code&amp;gt; in the server console. You should see a line that says &amp;lt;code&amp;gt;Metamod:Source version 2.x.x&amp;lt;/code&amp;gt;.&lt;br /&gt;
If it doesn't recognize the command, the installation probably failed. Try updating your game to the latest version and using the latest version of Source 2.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;For more information or documentation, see [[:Category:Metamod:Source Documentation]]&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Metamod:Source Documentation]]&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11725</id>
		<title>Porting to x64</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11725"/>
		<updated>2024-08-01T14:19:37Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Recompiling Extensions */ Mention usage of --targets&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Many plugins are already compatible with the x64 architecture, but many that manipulate game memory (such as with hooks or patches) will require extensive revisions to run under the new 64-bit servers.&lt;br /&gt;
Overall, if your plugin:&lt;br /&gt;
* Uses the address natives or the Address type,&lt;br /&gt;
* Uses dhooks&lt;br /&gt;
* Uses sdkcalls or sdktools (''not sdkhooks'')&lt;br /&gt;
&lt;br /&gt;
...you will need to update your plugin for 64 bits.&lt;br /&gt;
&lt;br /&gt;
Extensions may be good to go with just a recompile for 64-bits, but some may need more extensives changes.&lt;br /&gt;
&lt;br /&gt;
== I'm having an issue! ==&lt;br /&gt;
&lt;br /&gt;
In general, '''prototypes need to be exactly correct''' (including class statics like copy/destruct/constructors) as there are now significantly more quirks that will cause ABIs to be laid out differently.&lt;br /&gt;
&lt;br /&gt;
Here are some things to check for that may be tripping you up:&lt;br /&gt;
&lt;br /&gt;
* The type you thought was an ''int'' was actually a ''size_t''!&lt;br /&gt;
* The type you put down as an int or pointer was actually a ''float''!&lt;br /&gt;
* Handling pointers as ''int''s when they should be ''void*'' or ''size_t'' (why would you do this??)&lt;br /&gt;
* '''The calling convention has changed.''' Make sure to account for this in detours and patches. Make sure your prototypes are exactly correct!&lt;br /&gt;
* '''In patches:''' Did you forget the 64-bit opcode prefix when assembling your patch? EAX and RAX are accessed using different opcode prefixes!&lt;br /&gt;
&lt;br /&gt;
=== Linux Calling Convention Quirks ===&lt;br /&gt;
&lt;br /&gt;
Linux uses the System-V x64 ABI. There are many great sources of documentation all over the internet: [https://wiki.osdev.org/System_V_ABI OSDev Wiki] [https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions Wikipedia]&lt;br /&gt;
* All calling conventions are now an up to 8-register fastcall depending on the types (!!)&lt;br /&gt;
* RCX can be a thisptr, first argument, or stack return pointer depending on the context&lt;br /&gt;
* '''Integer arguments and float arguments are passed in different registers!''' (generic for ints, SIMD registers for floats)&lt;br /&gt;
* Varargs are now more complex to call when floats are included in the vararg&lt;br /&gt;
&lt;br /&gt;
The exact value of return types with C++ shenanigans (destructors, etc) still needs to be figured out by someone. However, in general.&lt;br /&gt;
* The return argument is always passed in RCX, and will bump the thisptr to RDX (todo: confirm this)&lt;br /&gt;
* Some return types that are 128-bits will be returned in both RAX and RDX??&lt;br /&gt;
&lt;br /&gt;
=== MSVC Calling Convention Quirks ===&lt;br /&gt;
Microsoft has some excellent official documentation [https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170 in their MSVC docs].&lt;br /&gt;
&lt;br /&gt;
* All calling conventions are now a four-register fastcall&lt;br /&gt;
* RCX can be a thisptr OR the first arg! It is not always a thisptr now. RCX can also be the return value (see below), bumping the thisptr to RDX.&lt;br /&gt;
* '''Integer arguments and float arguments are passed in different registers!''' (generic for ints, SIMD registers for floats)&lt;br /&gt;
* All objects larger than 8 bytes are now passed exclusively by reference (even on the stack??)&lt;br /&gt;
* Float arguments passed to varargs need to be put in both the generic and SIMD register for the appropiate argument index. Varargs are still fastcalls... somehow...&lt;br /&gt;
* '''setjmp has new behavior''' and destroys objects as if the scope has been exited. (if you ''are'' using setjmp, good luck)&lt;br /&gt;
&lt;br /&gt;
Return types also have their usual obscure shenanigans. More specifically,&lt;br /&gt;
* The return argument is always passed in RCX, and will bump the thisptr to RDX (todo: confirm this)&lt;br /&gt;
* Returns with all types larger than 8 bytes occur on the stack&lt;br /&gt;
* Returns with any type that has a user-defined base classes, virtual methods, constructor, destructor, or copy operation happens on the stack (''regardless of size'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Porting Plugins ==&lt;br /&gt;
&lt;br /&gt;
=== Gamedata ===&lt;br /&gt;
&lt;br /&gt;
All signatures will need to be updated, and likely many offsets.&lt;br /&gt;
&lt;br /&gt;
==== Gamedata key names ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot;| Arch/OS&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Linux&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Windows&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot;| x86&lt;br /&gt;
| linux&lt;br /&gt;
| windows&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot;| x64&lt;br /&gt;
| linux64&lt;br /&gt;
| windows64&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Address Natives ===&lt;br /&gt;
&lt;br /&gt;
New address natives that support 64-bits are still under development&lt;br /&gt;
&lt;br /&gt;
=== DHooks ===&lt;br /&gt;
&lt;br /&gt;
DHooks does not support 64-bits at all for the time being. It will need heavy revisions to work under the new architecture, starting with better SourceHook support for the 64-bit architecture (see: hookmangen)&lt;br /&gt;
&lt;br /&gt;
=== SDKCalls ===&lt;br /&gt;
&lt;br /&gt;
SDKCalls will need to be updated to learn how to accept a thisptr. However, all non-raw calls (eg, those to entities or gamerules that does not require a thisptr) should be fine as long as none of the arguments are 64-bits (including 64-bit ints!)&lt;br /&gt;
&lt;br /&gt;
== Recompiling Extensions ==&lt;br /&gt;
&lt;br /&gt;
The short version is that, assuming your target project uses AMBuild, pull in [https://github.com/alliedmodders/sourcemod/pull/2107 a modern revision of the build scripts], then specify the &amp;lt;code&amp;gt;--targets&amp;lt;/code&amp;gt; argument to build the extension for one or more supported architectures.&lt;br /&gt;
&lt;br /&gt;
Beyond that, as long as the code isn't architecture-specific, most extensions should compile fine with 64-bit support with slight adjustments at most.  If you are using detours, you may need to [https://github.com/alliedmodders/sourcemod/blob/96727a7610a2690b20670264edb737a42f9da110/AMBuildScript#L583-L591 make further adjustments to build the new safetyhook dependency].&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11724</id>
		<title>Porting to x64</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11724"/>
		<updated>2024-08-01T14:13:03Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Recompiling Extensions */ Reword &amp;quot;just update AMBuild&amp;quot;, add safetyhook&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Many plugins are already compatible with the x64 architecture, but many that manipulate game memory (such as with hooks or patches) will require extensive revisions to run under the new 64-bit servers.&lt;br /&gt;
Overall, if your plugin:&lt;br /&gt;
* Uses the address natives or the Address type,&lt;br /&gt;
* Uses dhooks&lt;br /&gt;
* Uses sdkcalls or sdktools (''not sdkhooks'')&lt;br /&gt;
&lt;br /&gt;
...you will need to update your plugin for 64 bits.&lt;br /&gt;
&lt;br /&gt;
Extensions may be good to go with just a recompile for 64-bits, but some may need more extensives changes.&lt;br /&gt;
&lt;br /&gt;
== I'm having an issue! ==&lt;br /&gt;
&lt;br /&gt;
In general, '''prototypes need to be exactly correct''' (including class statics like copy/destruct/constructors) as there are now significantly more quirks that will cause ABIs to be laid out differently.&lt;br /&gt;
&lt;br /&gt;
Here are some things to check for that may be tripping you up:&lt;br /&gt;
&lt;br /&gt;
* The type you thought was an ''int'' was actually a ''size_t''!&lt;br /&gt;
* The type you put down as an int or pointer was actually a ''float''!&lt;br /&gt;
* Handling pointers as ''int''s when they should be ''void*'' or ''size_t'' (why would you do this??)&lt;br /&gt;
* '''The calling convention has changed.''' Make sure to account for this in detours and patches. Make sure your prototypes are exactly correct!&lt;br /&gt;
* '''In patches:''' Did you forget the 64-bit opcode prefix when assembling your patch? EAX and RAX are accessed using different opcode prefixes!&lt;br /&gt;
&lt;br /&gt;
=== Linux Calling Convention Quirks ===&lt;br /&gt;
&lt;br /&gt;
Linux uses the System-V x64 ABI. There are many great sources of documentation all over the internet: [https://wiki.osdev.org/System_V_ABI OSDev Wiki] [https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions Wikipedia]&lt;br /&gt;
* All calling conventions are now an up to 8-register fastcall depending on the types (!!)&lt;br /&gt;
* RCX can be a thisptr, first argument, or stack return pointer depending on the context&lt;br /&gt;
* '''Integer arguments and float arguments are passed in different registers!''' (generic for ints, SIMD registers for floats)&lt;br /&gt;
* Varargs are now more complex to call when floats are included in the vararg&lt;br /&gt;
&lt;br /&gt;
The exact value of return types with C++ shenanigans (destructors, etc) still needs to be figured out by someone. However, in general.&lt;br /&gt;
* The return argument is always passed in RCX, and will bump the thisptr to RDX (todo: confirm this)&lt;br /&gt;
* Some return types that are 128-bits will be returned in both RAX and RDX??&lt;br /&gt;
&lt;br /&gt;
=== MSVC Calling Convention Quirks ===&lt;br /&gt;
Microsoft has some excellent official documentation [https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170 in their MSVC docs].&lt;br /&gt;
&lt;br /&gt;
* All calling conventions are now a four-register fastcall&lt;br /&gt;
* RCX can be a thisptr OR the first arg! It is not always a thisptr now. RCX can also be the return value (see below), bumping the thisptr to RDX.&lt;br /&gt;
* '''Integer arguments and float arguments are passed in different registers!''' (generic for ints, SIMD registers for floats)&lt;br /&gt;
* All objects larger than 8 bytes are now passed exclusively by reference (even on the stack??)&lt;br /&gt;
* Float arguments passed to varargs need to be put in both the generic and SIMD register for the appropiate argument index. Varargs are still fastcalls... somehow...&lt;br /&gt;
* '''setjmp has new behavior''' and destroys objects as if the scope has been exited. (if you ''are'' using setjmp, good luck)&lt;br /&gt;
&lt;br /&gt;
Return types also have their usual obscure shenanigans. More specifically,&lt;br /&gt;
* The return argument is always passed in RCX, and will bump the thisptr to RDX (todo: confirm this)&lt;br /&gt;
* Returns with all types larger than 8 bytes occur on the stack&lt;br /&gt;
* Returns with any type that has a user-defined base classes, virtual methods, constructor, destructor, or copy operation happens on the stack (''regardless of size'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Porting Plugins ==&lt;br /&gt;
&lt;br /&gt;
=== Gamedata ===&lt;br /&gt;
&lt;br /&gt;
All signatures will need to be updated, and likely many offsets.&lt;br /&gt;
&lt;br /&gt;
==== Gamedata key names ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot;| Arch/OS&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Linux&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Windows&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot;| x86&lt;br /&gt;
| linux&lt;br /&gt;
| windows&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot;| x64&lt;br /&gt;
| linux64&lt;br /&gt;
| windows64&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Address Natives ===&lt;br /&gt;
&lt;br /&gt;
New address natives that support 64-bits are still under development&lt;br /&gt;
&lt;br /&gt;
=== DHooks ===&lt;br /&gt;
&lt;br /&gt;
DHooks does not support 64-bits at all for the time being. It will need heavy revisions to work under the new architecture, starting with better SourceHook support for the 64-bit architecture (see: hookmangen)&lt;br /&gt;
&lt;br /&gt;
=== SDKCalls ===&lt;br /&gt;
&lt;br /&gt;
SDKCalls will need to be updated to learn how to accept a thisptr. However, all non-raw calls (eg, those to entities or gamerules that does not require a thisptr) should be fine as long as none of the arguments are 64-bits (including 64-bit ints!)&lt;br /&gt;
&lt;br /&gt;
== Recompiling Extensions ==&lt;br /&gt;
&lt;br /&gt;
The short version is that, assuming your target project uses AMBuild, pull in [https://github.com/alliedmodders/sourcemod/pull/2107 a modern revision of the build scripts].&lt;br /&gt;
&lt;br /&gt;
Beyond that, as long as the code isn't architecture-specific, most extensions should compile fine with 64-bit support with slight adjustments at most.  If you are using detours, you may need to [https://github.com/alliedmodders/sourcemod/blob/96727a7610a2690b20670264edb737a42f9da110/AMBuildScript#L583-L591 make further adjustments to build the new safetyhook dependency].&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11723</id>
		<title>Porting to x64</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Porting_to_x64&amp;diff=11723"/>
		<updated>2024-08-01T14:03:57Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: Add section on recompiling extensions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Many plugins are already compatible with the x64 architecture, but many that manipulate game memory (such as with hooks or patches) will require extensive revisions to run under the new 64-bit servers.&lt;br /&gt;
Overall, if your plugin:&lt;br /&gt;
* Uses the address natives or the Address type,&lt;br /&gt;
* Uses dhooks&lt;br /&gt;
* Uses sdkcalls or sdktools (''not sdkhooks'')&lt;br /&gt;
&lt;br /&gt;
...you will need to update your plugin for 64 bits.&lt;br /&gt;
&lt;br /&gt;
Extensions may be good to go with just a recompile for 64-bits, but some may need more extensives changes.&lt;br /&gt;
&lt;br /&gt;
== I'm having an issue! ==&lt;br /&gt;
&lt;br /&gt;
In general, '''prototypes need to be exactly correct''' (including class statics like copy/destruct/constructors) as there are now significantly more quirks that will cause ABIs to be laid out differently.&lt;br /&gt;
&lt;br /&gt;
Here are some things to check for that may be tripping you up:&lt;br /&gt;
&lt;br /&gt;
* The type you thought was an ''int'' was actually a ''size_t''!&lt;br /&gt;
* The type you put down as an int or pointer was actually a ''float''!&lt;br /&gt;
* Handling pointers as ''int''s when they should be ''void*'' or ''size_t'' (why would you do this??)&lt;br /&gt;
* '''The calling convention has changed.''' Make sure to account for this in detours and patches. Make sure your prototypes are exactly correct!&lt;br /&gt;
* '''In patches:''' Did you forget the 64-bit opcode prefix when assembling your patch? EAX and RAX are accessed using different opcode prefixes!&lt;br /&gt;
&lt;br /&gt;
=== Linux Calling Convention Quirks ===&lt;br /&gt;
&lt;br /&gt;
Linux uses the System-V x64 ABI. There are many great sources of documentation all over the internet: [https://wiki.osdev.org/System_V_ABI OSDev Wiki] [https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions Wikipedia]&lt;br /&gt;
* All calling conventions are now an up to 8-register fastcall depending on the types (!!)&lt;br /&gt;
* RCX can be a thisptr, first argument, or stack return pointer depending on the context&lt;br /&gt;
* '''Integer arguments and float arguments are passed in different registers!''' (generic for ints, SIMD registers for floats)&lt;br /&gt;
* Varargs are now more complex to call when floats are included in the vararg&lt;br /&gt;
&lt;br /&gt;
The exact value of return types with C++ shenanigans (destructors, etc) still needs to be figured out by someone. However, in general.&lt;br /&gt;
* The return argument is always passed in RCX, and will bump the thisptr to RDX (todo: confirm this)&lt;br /&gt;
* Some return types that are 128-bits will be returned in both RAX and RDX??&lt;br /&gt;
&lt;br /&gt;
=== MSVC Calling Convention Quirks ===&lt;br /&gt;
Microsoft has some excellent official documentation [https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170 in their MSVC docs].&lt;br /&gt;
&lt;br /&gt;
* All calling conventions are now a four-register fastcall&lt;br /&gt;
* RCX can be a thisptr OR the first arg! It is not always a thisptr now. RCX can also be the return value (see below), bumping the thisptr to RDX.&lt;br /&gt;
* '''Integer arguments and float arguments are passed in different registers!''' (generic for ints, SIMD registers for floats)&lt;br /&gt;
* All objects larger than 8 bytes are now passed exclusively by reference (even on the stack??)&lt;br /&gt;
* Float arguments passed to varargs need to be put in both the generic and SIMD register for the appropiate argument index. Varargs are still fastcalls... somehow...&lt;br /&gt;
* '''setjmp has new behavior''' and destroys objects as if the scope has been exited. (if you ''are'' using setjmp, good luck)&lt;br /&gt;
&lt;br /&gt;
Return types also have their usual obscure shenanigans. More specifically,&lt;br /&gt;
* The return argument is always passed in RCX, and will bump the thisptr to RDX (todo: confirm this)&lt;br /&gt;
* Returns with all types larger than 8 bytes occur on the stack&lt;br /&gt;
* Returns with any type that has a user-defined base classes, virtual methods, constructor, destructor, or copy operation happens on the stack (''regardless of size'')&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Porting Plugins ==&lt;br /&gt;
&lt;br /&gt;
=== Gamedata ===&lt;br /&gt;
&lt;br /&gt;
All signatures will need to be updated, and likely many offsets.&lt;br /&gt;
&lt;br /&gt;
==== Gamedata key names ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot;| Arch/OS&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Linux&lt;br /&gt;
! scope=&amp;quot;col&amp;quot;| Windows&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot;| x86&lt;br /&gt;
| linux&lt;br /&gt;
| windows&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot;| x64&lt;br /&gt;
| linux64&lt;br /&gt;
| windows64&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Address Natives ===&lt;br /&gt;
&lt;br /&gt;
New address natives that support 64-bits are still under development&lt;br /&gt;
&lt;br /&gt;
=== DHooks ===&lt;br /&gt;
&lt;br /&gt;
DHooks does not support 64-bits at all for the time being. It will need heavy revisions to work under the new architecture, starting with better SourceHook support for the 64-bit architecture (see: hookmangen)&lt;br /&gt;
&lt;br /&gt;
=== SDKCalls ===&lt;br /&gt;
&lt;br /&gt;
SDKCalls will need to be updated to learn how to accept a thisptr. However, all non-raw calls (eg, those to entities or gamerules that does not require a thisptr) should be fine as long as none of the arguments are 64-bits (including 64-bit ints!)&lt;br /&gt;
&lt;br /&gt;
== Recompiling Extensions ==&lt;br /&gt;
&lt;br /&gt;
The short version is to pull in [https://github.com/alliedmodders/sourcemod/pull/2107 a modern revision of the build scripts], assuming the target project is using that build tooling.&lt;br /&gt;
&lt;br /&gt;
Beyond that, as long as the code isn't architecture-specific, most extensions should compile fine with 64-bit support with slight adjustments at most.&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11701</id>
		<title>User:Nosoop/Guide/Advanced</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11701"/>
		<updated>2024-06-11T04:19:22Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Virtual Hook or Detour? */ Add note on symbol aliasing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section is provided for users that want or need to work with game-specific functionality that SourceMod doesn't provide access to out of the box.&lt;br /&gt;
&lt;br /&gt;
It's assumed that you're comfortable with programming and various terms.  By the end of this page you'll have some knowledge of calling / hooking arbitrary functions in the game.&lt;br /&gt;
&lt;br /&gt;
= What is gamedata? =&lt;br /&gt;
&lt;br /&gt;
''Gamedata'', also known as game data, gameconfig, and gameconf, are files used to specify information tied to a specific game.&lt;br /&gt;
&lt;br /&gt;
As the games that SourceMod runs on are updated independently of SourceMod itself, gamedata is used as a unified way to keep plugins and extensions up to date on game changes without needing to recompile them.&lt;br /&gt;
&lt;br /&gt;
= Finding Functions =&lt;br /&gt;
&lt;br /&gt;
* TODO refer to public SDK if you don't know what you're looking for&lt;br /&gt;
* TODO explain what to do in a game with symbols&lt;br /&gt;
* TODO suggest opening IDA's options and enabling opcode bytes&lt;br /&gt;
* TODO inlined functions&lt;br /&gt;
* TODO debugging&lt;br /&gt;
&lt;br /&gt;
= Finding VTable Offsets =&lt;br /&gt;
&lt;br /&gt;
In C++, a ''virtual method table'' (shorthand &amp;amp;quot;vtable&amp;amp;quot;) is effectively an array of function pointers. It's intended for inheritance — a virtual &amp;lt;code&amp;gt;::DoThing()&amp;lt;/code&amp;gt; method can be different for different classes, and so the code will look up the correct function for a specific instance based on the table for the instance's class. Every class that uses a vtable will hold a reference to it as one of its properties.&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
Once you have the virtual call, jump to its reference in &amp;lt;tt&amp;gt;.rodata&amp;lt;/tt&amp;gt; and make a note of that address.  Scroll up until you see an offset reference (&amp;lt;tt&amp;gt;off_*&amp;lt;/tt&amp;gt; in IDA, &amp;lt;tt&amp;gt;PTR_*&amp;lt;/tt&amp;gt; in Ghidra); that is likely the first entry in the vtable (index 0).  This reference is created by disassemblers as this is the address that is stored in class instances.&lt;br /&gt;
&lt;br /&gt;
Get the difference between your virtual call's address and that of the first entry, then divide by the pointer size (4 on 32-bit platforms, 8 on 64-bit).&lt;br /&gt;
&lt;br /&gt;
For example, given a 32-bit function pointer located at &amp;lt;tt&amp;gt;011AE84Ch&amp;lt;/tt&amp;gt; and the start at &amp;lt;tt&amp;gt;011AE3C8h&amp;lt;/tt&amp;gt;, you do &amp;lt;tt&amp;gt;(0x011AE84C-0x011AE3C8) / 4&amp;lt;/tt&amp;gt;, resulting in the index 289.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if you're familiar with the code or have sources to cross-reference against, you can search for the virtual call itself.  In a Linux disassembly, it will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; get the first vtable by dereferencing the pointer at the start of the class instance&lt;br /&gt;
8B 03       mov  eax, [ebx]&lt;br /&gt;
&lt;br /&gt;
; push the class instance as a parameter&lt;br /&gt;
89 1C 24    mov  [esp], ebx&lt;br /&gt;
&lt;br /&gt;
; call the fourth entry (at index 3) in the vtable: 0xC / sizeof(void*) = 0x3&lt;br /&gt;
FF 50 0C    call dword ptr [eax+0Ch]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If the game isn't stripped of debugging symbols, use [https://asherkin.github.io/vtable/ asherkin's VTable Dumper].  It provides correct offsets for Linux binaries (as it's what it works with), and estimates usually correct offsets for Windows.&lt;br /&gt;
&lt;br /&gt;
There are instances where the dumper isn't correct, so you may need to be careful in those cases.  Known cases include:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/asherkin/vtable/issues/7 Classes that have discontinuous overloaded functions]&lt;br /&gt;
* Possibly multiple inheritance&lt;br /&gt;
&lt;br /&gt;
Aside - the layout of vtables is not the same across platforms.  Notable differences are:&lt;br /&gt;
&lt;br /&gt;
# Linux may have multiple virtual destructors; Windows appears to only have up to one.&lt;br /&gt;
# Linux overloads are in the same order as they are initially defined in the original code.  On Windows, this is the same, except that overloaded functions (those with the same name that accept different parameters) are grouped together and emitted in reverse order.&lt;br /&gt;
&lt;br /&gt;
= Creating Signatures =&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
After you've found a function, you need to tell SourceMod the sequence of bytes unique to it. Those bytes make up a ''signature''.&lt;br /&gt;
&lt;br /&gt;
{{Note|If you're using IDA and only see the mnemonics in the &amp;quot;IDA View&amp;quot; tab, make sure to set the number of opcode bytes in IDA options to a non-zero number.  8 is sufficient in most cases.}}&lt;br /&gt;
&lt;br /&gt;
You could treat just the sequence bytes as the signature directly, but this would break very easily whenever the game is updated. At the machine-code level, the ''instructions'' might be the same for &amp;amp;quot;move X to Y&amp;amp;quot;, but the ''data'' might change — X and Y might be in a different location in the binary altogether. For an example within a longer signature:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; sets esp to the offset aString&lt;br /&gt;
; the bytes 3B B3 25 01 are the absolute offset of aString in this binary in little-endian format (0x0125B33B)&lt;br /&gt;
C7 04 24 3B B3 25 01    mov     dword ptr [esp], offset aString&lt;br /&gt;
&lt;br /&gt;
; call function, the four bytes after E8 are the location of the function&lt;br /&gt;
E8 78 F0 48 00          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
&lt;br /&gt;
; sets eax to arg 0&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The naive signature for that would be &amp;lt;code&amp;gt;\xC7\x04\x24\x3B\xB3\x25\x01\xE8\x78\xF0\x48\x00\x8B\x45\x08&amp;lt;/code&amp;gt;. However, you can't rely on those bytes mentioned to be constant at all:&lt;br /&gt;
&lt;br /&gt;
* The offsets of &amp;lt;code&amp;gt;aString&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UTIL_VarArgs&amp;lt;/code&amp;gt; might be located somewhere else after a game update&lt;br /&gt;
* Relocations may be performed such that the data bytes are different in memory from its on-disk representation&lt;br /&gt;
&lt;br /&gt;
As a solution to this, you use wildcards to mask off the bytes you don't care about. For SourceMod game config files, the sequence &amp;lt;code&amp;gt;\x2A&amp;lt;/code&amp;gt; indicates that particular byte shouldn't be checked and to continue to the next one.&lt;br /&gt;
&lt;br /&gt;
Here is what the previous signature looks like with the masked bytes displayed as &amp;lt;code&amp;gt;??&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
C7 04 24 ?? ?? ?? ??    mov     dword ptr [esp], offset aString&lt;br /&gt;
E8 ?? ?? ?? ??          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A masked signature would then be &amp;lt;code&amp;gt;\xC7\x04\x24\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x45\x08&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Masking is used mainly for offsets, such as for functions and variables. Instructions generally don't change unless the function code itself is modified, at which point you'll want to revisit your binary and update accordingly.&lt;br /&gt;
&lt;br /&gt;
If you're using DHooks with byte signatures (covered later), you may want to also mask out the first six bytes, as a detour will patch in an unconditional JMP at the start to trampoline into a user-defined function, and subsequent scans for the byte signature will fail.&lt;br /&gt;
&lt;br /&gt;
{{Note|This is no longer the case as of SourceMod 1.11, which stores a copy of the original data for scanning purposes.  However, it's noted here for historical / implementation detail reasons.}}&lt;br /&gt;
&lt;br /&gt;
For an extended lesson, you can look at the following material:&lt;br /&gt;
&lt;br /&gt;
* [https://wiki.alliedmods.net/Signature_Scanning Signature Scanning] on the AlliedModders wiki&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If you're using IDA (including Free), use the [https://github.com/alliedmodders/sourcemod/blob/master/tools/ida_scripts/makesig7.idc &amp;lt;code&amp;gt;makesig7.idc&amp;lt;/code&amp;gt;] script. If you're using Ghidra, use [https://github.com/alliedmodders/sourcemod/blob/master/tools/ghidra_scripts/makesig.py &amp;lt;code&amp;gt;makesig.py&amp;lt;/code&amp;gt;].&lt;br /&gt;
&lt;br /&gt;
They generally do pretty well at finding and masking byte signatures, but when it fails or you want a more robust signature, you should understand how to create the signatures manually.&lt;br /&gt;
&lt;br /&gt;
Both scripts may produce different byte signatures for the same function due to using different methods to determine if a given byte should be masked.&lt;br /&gt;
&lt;br /&gt;
It's exceedingly rare, but possible that the binary has two copies of the exact same short function (for example, when they are typechecked and statically casted to different subclasses). Both scripts will fail in that case. SourceMod's signature scanner will use the first match it finds, so if any match is acceptable, you can still use an appropriately masked signature.&lt;br /&gt;
&lt;br /&gt;
If two copies of a function seem to exist, be sure to look at the disassembly to make sure that the functions are indeed the same.&lt;br /&gt;
&lt;br /&gt;
= Finding Addresses =&lt;br /&gt;
&lt;br /&gt;
Sometimes you have a symbol, but you need an address to work with.  That is what the &amp;quot;Addresses&amp;quot; section of a game configuration file is used for.&lt;br /&gt;
&lt;br /&gt;
To find an address, you start from a known location reference (signature).  You may then have to jump to references (that is, dereference locations), then get an offset from the previous reference.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; keys indicate an offset to load / dereference relative to the previous address, and &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; means to shift the previous address without any dereference.  These key / value pairs are processed in the order you specify them in the file; &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; is only valid as the last &amp;quot;operation&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For a C++-like example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// start from an address&lt;br /&gt;
// &amp;quot;FindLocation&amp;quot; would return the location of either a named symbol reference or the start of a byte signature&lt;br /&gt;
uintptr_t addr = FindLocation(&amp;quot;some_signature&amp;quot;);&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr + 40); // gameconf: &amp;quot;read&amp;quot; &amp;quot;40&amp;quot;&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr); // gameconf: &amp;quot;read&amp;quot; &amp;quot;0&amp;quot;&lt;br /&gt;
addr += 13; // gameconf: &amp;quot;offset&amp;quot; &amp;quot;13&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Calling Game Functions =&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== SDKCall Order ==&lt;br /&gt;
&lt;br /&gt;
When performing an {{SourceMod API|file=sdktools|function=SDKCall}}, the parameters need to be passed in the following order:&lt;br /&gt;
&lt;br /&gt;
# The SDKCall handle received from {{SourceMod API|file=sdktools|function=EndPrepSDKCall}}.&lt;br /&gt;
# The &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; instance.  &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; may be omitted in the following cases:&lt;br /&gt;
#* The function was declared as static, where there is no &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; to pass in.&lt;br /&gt;
#* The function was declared with the &amp;lt;tt&amp;gt;SDKCall_GameRules&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SDKCall_EntityList&amp;lt;/tt&amp;gt; call types; SDKTools itself will provide the appropriate global instance.&lt;br /&gt;
# The return buffer, if applicable.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;Vector&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;QAngle&amp;lt;/tt&amp;gt;, the parameter is a &amp;lt;tt&amp;gt;float[3]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt;, the parameters should be a &amp;lt;tt&amp;gt;char[]&amp;lt;/tt&amp;gt; buffer and an &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; specifying the size of the buffer.  The return value of the SDKCall will be the number of characters written, or -1 if the function returned a null pointer (to differentiate between an empty string).&lt;br /&gt;
#* If the function returns a primitive type / entity / edict, it will be the return value of the SDKCall, so no such return buffer is necessary.&lt;br /&gt;
# Any remaining parameters for the function.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// Vector CBaseCombatCharacter::Weapon_ShootPosition() -- has 'this' and 'Vector' return&lt;br /&gt;
float vecShootPosition[3];&lt;br /&gt;
SDKCall(g_hSDKCall, client, vecShootPosition);&lt;br /&gt;
&lt;br /&gt;
// const char *CBaseAnimating::GetSequenceName(int iSequence) -- has 'this', 'char*' return, and parameter&lt;br /&gt;
char sequenceName[64];&lt;br /&gt;
SDKCall(g_hSDKCall, entity, sequenceName, sizeof(sequenceName), iSequence);&lt;br /&gt;
&lt;br /&gt;
// bool CGlobalEntityList::IsEntityPtr(void* pTest) -- SDKCall_EntityList is used, so no 'this' explicitly needed&lt;br /&gt;
// SDKCall passes the return value from the called function as its return value, so use an assignment operator&lt;br /&gt;
Address pTest;&lt;br /&gt;
bool result = SDKCall(g_hSDKCall, pTest);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calling via Signature or Offset? ==&lt;br /&gt;
&lt;br /&gt;
If you have a class with a virtual method, you generally should set up the &amp;lt;tt&amp;gt;SDKCall&amp;lt;/tt&amp;gt; to take a virtual offset.  Doing so allows your plugin to have the expected interactions with other plugin's hooks, covered in the next section.&lt;br /&gt;
&lt;br /&gt;
You should use a signature either when the function is not virtual or if you need to bypass the virtual override on an entity (e.g. calling the parent class's function).  In those instances, only detours will take effect.&lt;br /&gt;
&lt;br /&gt;
= Hooking Game Functions (with DHooks) =&lt;br /&gt;
&lt;br /&gt;
DHooks is an extension bundled with SourceMod that enables plugins to hook functions of their choosing (currently restricted to those accessible via server / engine binaries).  You may use its functionality by including {{SourceMod API|file=dhooks}}.&lt;br /&gt;
&lt;br /&gt;
As with {{SourceMod API|file=sdktools|function=SDKCall}}s, you must ensure that your hook setup is declared with the same parameter and return types to ensure the server continues to operate as you'd expect.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== Virtual Hook or Detour? ==&lt;br /&gt;
&lt;br /&gt;
A virtual hook is mainly used for hooking virtual methods of a class; a detour is used for hooking any function.&lt;br /&gt;
&lt;br /&gt;
While detours can be used to hook the function a virtual table calls into, virtual hooks still have the merit of hooking specific classes / instances.  More specifically:&lt;br /&gt;
&lt;br /&gt;
* DHooks provides the bookkeeping on which instances are and aren't hooked, so for virtual hooks the callback will only be invoked on those you specifically hook.  On detours, you have to filter on instances yourself.&lt;br /&gt;
* On chained inheritance, a virtual hook will only act on the exact class and not any parent nor subclasses, even if they all point to the same virtual function.  Detours will, again, be called on any invocation of the function, including calls to it made by its subclass.&lt;br /&gt;
* On some binaries (especially with more aggressive optimizations in place), multiple function symbols may map to the same place in memory if they output the same code.  As a result, detours may be called when you don't expect them to be.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11685</id>
		<title>User:Nosoop/Guide/Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11685"/>
		<updated>2024-04-27T22:35:46Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: Fix spacing&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section assumes that you're starting out with nothing besides a desktop computer, an internet connection, and a drive to program some SourceMod plugins. No programming experience; no problem.&lt;br /&gt;
&lt;br /&gt;
This page will walk you through manually installing the dedicated server software for your desired game, installing SourceMod, and selecting a text editor to use for development.&lt;br /&gt;
&lt;br /&gt;
There are a number of third-party tools that can automate most of these steps, but we'll stick to the first-party approach here to avoid abstractions from breaking under you.&lt;br /&gt;
&lt;br /&gt;
If you are using a third-party tool to manage your server installation, refer to the tool's documentation for their instructions, then skip to [[#Installing SourceMod|Installing SourceMod]] to download the scripting toolchain for your desktop operating system.&lt;br /&gt;
&lt;br /&gt;
= Installing the Server =&lt;br /&gt;
&lt;br /&gt;
{{note|&amp;lt;p&amp;gt;While officially unsupported, SourceMod may be loaded on a game client (the game you launch); the server a game client creates is known as a listen server. However, there are many behavioral quirks that can only be reproduced on a listen server, and you likely won't receive any solutions to those issues that aren't &amp;quot;use a dedicated server&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This guide does not provide instructions to load SourceMod on a game client. It's highly recommended to stick to installing SourceMod on dedicated game server instances to ensure that any plugins you write will have the correct behavior.&amp;lt;/p&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
To install the dedicated server software for the game of your choice, we will use &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt;. If a game server provider (GSP) is hosting the server for you, skip this step as your provider has already provided you with an installation; if you are using a self-hosted game server management panel, refer to the instructions for your software of choice to install your game server in place of this step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is Valve's command-line Steam client. It is used to install and update dedicated game servers.&lt;br /&gt;
&lt;br /&gt;
Refer to [https://developer.valvesoftware.com/wiki/SteamCMD the SteamCMD entry] in the Valve Developer Wiki for download instructions. This varies on the operating system you're running the software on; you can either work on your own desktop or have a hosted (physical or virtual) machine off-premises.&lt;br /&gt;
&lt;br /&gt;
Once &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is extracted, you will need to install a game server. Continue reading the above wiki page to [https://developer.valvesoftware.com/wiki/SteamCMD#Running_SteamCMD run the application], [https://developer.valvesoftware.com/wiki/SteamCMD#SteamCMD_Login sign in (anonymously)], and [https://developer.valvesoftware.com/wiki/SteamCMD#Downloading_an_App download your game server].&lt;br /&gt;
&lt;br /&gt;
You will need the AppID of the game's dedicated server to install it; note that it is different from the game client AppIDs.  See the below table for that and additional related information for some of the supported games.&lt;br /&gt;
&lt;br /&gt;
{{note|Be sure to write down the commands you used when installing the game server!  You will need to issue those commands again whenever the game is updated.}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Dedicated Server Information&lt;br /&gt;
|-&lt;br /&gt;
! Game&lt;br /&gt;
! AppID&lt;br /&gt;
! Mod Directory&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Day of Defeat: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232290&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;dod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Team Fortress 2&lt;br /&gt;
| &amp;lt;code&amp;gt;232250&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;tf&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232330&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;cstrike&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Global Offensive&lt;br /&gt;
| &amp;lt;code&amp;gt;740&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* As of 1.38.5.2 (2023-02-02), servers running under Linux will need to have a relatively modern libstdc++ installed.  [https://www.mail-archive.com/csgo_servers@list.valvesoftware.com/msg14291.html See this mailing list entry for further details.]&lt;br /&gt;
* [[Introduction to SourceMod Plugins#Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported?|See the current state of Counter-Strike 2 here.]]&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead&lt;br /&gt;
| &amp;lt;code&amp;gt;222840&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* This is the one first-party game that requires a [https://www.metamodsource.net/?go=vdf custom VDF file for Metamod:Source].&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2&lt;br /&gt;
| &amp;lt;code&amp;gt;222860&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Half-Life 2: Deathmatch&lt;br /&gt;
| &amp;lt;code&amp;gt;232370&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;hl2mp&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| No More Room in Hell&lt;br /&gt;
| &amp;lt;code&amp;gt;317670&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;nmrih&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Zombie Panic! Source&lt;br /&gt;
| &amp;lt;code&amp;gt;17505&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;zps&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pirates, Vikings &amp;amp; Knights II&lt;br /&gt;
| &amp;lt;code&amp;gt;17575&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;pvkii&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For post-install server configuration, take a look at the [[../Game Server Configuration|Game Server Configuration]] page.&lt;br /&gt;
&lt;br /&gt;
= Installing Metamod:Source =&lt;br /&gt;
&lt;br /&gt;
Before you can install SourceMod on your server, you must first download and install Metamod:Source. Metamod:Source (MM:S) acts as a middleware for different Source Engine games, providing a unified interface for plugins to operate on the game.&lt;br /&gt;
&lt;br /&gt;
SourceMod itself is an MM:S plugin.&lt;br /&gt;
&lt;br /&gt;
# Download [http://www.metamodsource.net/ Metamod:Source]. In most cases, you want a stable release. Use the download package according to your server's operating system.&lt;br /&gt;
#* If the latest download is unavailable, go down the &amp;amp;quot;Latest 20 Builds&amp;amp;quot; until you get to one that is.&lt;br /&gt;
#* Again, make sure you're downloading the correct package for your server; if you're using a hosted instance, it may not be using the same operating system as your personal desktop.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
#* You may need to extract the archive on, or upload the contents to a remote server.&lt;br /&gt;
#** If you are on Windows, the recommended software to use for extracting Linux (&amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt;) archives is [https://www.7-zip.org/download.html 7-zip]; to upload files remotely via FTP, use [https://winscp.net/eng/index.php WinSCP].&lt;br /&gt;
#** If you are using a GSP, refer to their control panel.  Most provide FTP access, and some also allow for uploads directly via browser.&lt;br /&gt;
#** You should verify that the files were transmitted properly to the server; there have been reports of upload failures, zero-length files, and files that were mistakenly sent in text form and corrupted as a result.&lt;br /&gt;
# After installing, you should verify that the installation was successful by starting your server and running &amp;lt;tt&amp;gt;meta version&amp;lt;/tt&amp;gt;.  It should be treated as a known command at this stage.&lt;br /&gt;
#* Most games should work without further configuration, but if you find that MM:S isn't loading, you will want to [https://www.metamodsource.net/?go=vdf generate a custom VDF file].  Known games that require custom VDF files are:&lt;br /&gt;
#** Left 4 Dead 1&lt;br /&gt;
#** Third-party mods using the Source SDK base&lt;br /&gt;
#* Metamod:Source is known to fail to load on CS:GO servers running under Linux by default.  You will want to delete &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to the installation directory, plus read the information in the next bullet point.&lt;br /&gt;
#* If you are using a Linux server you have full control over, read over the [[User:Nosoop/Guide/Game Server Configuration#Platform-specific|Platform-specific setup]] information.&lt;br /&gt;
#* Additional diagnostic information about load failures is available under &amp;lt;tt&amp;gt;metamod-fatal.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Note|On server startup, you may see an error message &amp;lt;tt&amp;gt;Unable to load plugin &amp;quot;addons/metamod/bin/${platform}64/server&amp;quot;&amp;lt;/tt&amp;gt;.  This is normal behavior; the game server will always attempt to load both 32-bit and 64-bit binaries and fail on the one that doesn't match.  If you're sure that you're not running a 64-bit game server instance, you can delete &amp;lt;tt&amp;gt;addons/metamod_x64.vdf&amp;lt;/tt&amp;gt; to only load the 32-bit version, or the other way around.}}&lt;br /&gt;
&lt;br /&gt;
= Installing SourceMod =&lt;br /&gt;
&lt;br /&gt;
The following is mostly lifted from the [[Installing SourceMod]] page.&lt;br /&gt;
&lt;br /&gt;
# Download [https://www.sourcemod.net/ SourceMod]. Same as before; latest available stable release for your server's operating system.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If you plan on creating new plugins, you will also want to download SourceMod for your ''desktop'' operating system and extract the &amp;lt;code&amp;gt;addons/sourcemod/scripting/&amp;lt;/code&amp;gt; folder to a location on your computer.&lt;br /&gt;
&lt;br /&gt;
In the future, you may need to follow [[Upgrading SourceMod|these instructions to upgrade SourceMod]] on your server because of:&lt;br /&gt;
* game updates requiring SourceMod to be rebuilt against a new revision of the Source SDK&lt;br /&gt;
* plugins compiled against newer versions of SourceMod to take advantage of added functionality&lt;br /&gt;
&lt;br /&gt;
= Picking an IDE =&lt;br /&gt;
&lt;br /&gt;
Now that you have the dedicated game server, Metamod:Source, and SourceMod installed, you have most of the tools you need.&lt;br /&gt;
&lt;br /&gt;
If you've never done any programming, you'll need a text editor. It's completely possible to write code in plain old Notepad and invoke the compiler directly, but having a proper development environment makes it much easier to work with code.&lt;br /&gt;
&lt;br /&gt;
The following editors are known to have good support for SourceMod plugins:&lt;br /&gt;
&lt;br /&gt;
* Spider &amp;amp;mdash; recommended when starting out due to it being zero-install; once you are doing more than one-off plugins, move on to one of the non-web text editors&lt;br /&gt;
* Visual Studio Code (VSCode) &amp;amp;mdash; an increasingly popular choice combined with [https://marketplace.visualstudio.com/items?itemName=Sarrus.sourcepawn-vscode Sarrus's VSCode extension] [https://github.com/Sarrus1/sourcepawn-vscode (source code)]&lt;br /&gt;
* BasicPawn&lt;br /&gt;
* Notepad++&lt;br /&gt;
* SPEdit&lt;br /&gt;
* Sublime Text&lt;br /&gt;
&lt;br /&gt;
For more details on each editor and, if necessary, how to set it up for writing SourceMod plugins, look at the [[../Development Environments|Development Environments]] section of the guide.&lt;br /&gt;
&lt;br /&gt;
Once you've settled on a development environment, you can start learning how to create plugins &amp;amp;mdash; head over to the [[../Basics|Basics]] section of the guide to get started.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11684</id>
		<title>User:Nosoop/Guide/Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11684"/>
		<updated>2024-04-27T22:35:23Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Installing the Server */ Add reminder to note install commands&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section assumes that you're starting out with nothing besides a desktop computer, an internet connection, and a drive to program some SourceMod plugins. No programming experience; no problem.&lt;br /&gt;
&lt;br /&gt;
This page will walk you through manually installing the dedicated server software for your desired game, installing SourceMod, and selecting a text editor to use for development.&lt;br /&gt;
&lt;br /&gt;
There are a number of third-party tools that can automate most of these steps, but we'll stick to the first-party approach here to avoid abstractions from breaking under you.&lt;br /&gt;
&lt;br /&gt;
If you are using a third-party tool to manage your server installation, refer to the tool's documentation for their instructions, then skip to [[#Installing SourceMod|Installing SourceMod]] to download the scripting toolchain for your desktop operating system.&lt;br /&gt;
&lt;br /&gt;
= Installing the Server =&lt;br /&gt;
&lt;br /&gt;
{{note|&amp;lt;p&amp;gt;While officially unsupported, SourceMod may be loaded on a game client (the game you launch); the server a game client creates is known as a listen server. However, there are many behavioral quirks that can only be reproduced on a listen server, and you likely won't receive any solutions to those issues that aren't &amp;quot;use a dedicated server&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This guide does not provide instructions to load SourceMod on a game client. It's highly recommended to stick to installing SourceMod on dedicated game server instances to ensure that any plugins you write will have the correct behavior.&amp;lt;/p&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
To install the dedicated server software for the game of your choice, we will use &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt;. If a game server provider (GSP) is hosting the server for you, skip this step as your provider has already provided you with an installation; if you are using a self-hosted game server management panel, refer to the instructions for your software of choice to install your game server in place of this step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is Valve's command-line Steam client. It is used to install and update dedicated game servers.&lt;br /&gt;
&lt;br /&gt;
Refer to [https://developer.valvesoftware.com/wiki/SteamCMD the SteamCMD entry] in the Valve Developer Wiki for download instructions. This varies on the operating system you're running the software on; you can either work on your own desktop or have a hosted (physical or virtual) machine off-premises.&lt;br /&gt;
&lt;br /&gt;
Once &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is extracted, you will need to install a game server. Continue reading the above wiki page to [https://developer.valvesoftware.com/wiki/SteamCMD#Running_SteamCMD run the application], [https://developer.valvesoftware.com/wiki/SteamCMD#SteamCMD_Login sign in (anonymously)], and [https://developer.valvesoftware.com/wiki/SteamCMD#Downloading_an_App download your game server].&lt;br /&gt;
&lt;br /&gt;
You will need the AppID of the game's dedicated server to install it; note that it is different from the game client AppIDs.  See the below table for that and additional related information for some of the supported games.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{note|Be sure to write down the commands you used when installing the game server!  You will need to issue those commands again whenever the game is updated.}}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Dedicated Server Information&lt;br /&gt;
|-&lt;br /&gt;
! Game&lt;br /&gt;
! AppID&lt;br /&gt;
! Mod Directory&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Day of Defeat: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232290&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;dod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Team Fortress 2&lt;br /&gt;
| &amp;lt;code&amp;gt;232250&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;tf&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232330&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;cstrike&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Global Offensive&lt;br /&gt;
| &amp;lt;code&amp;gt;740&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* As of 1.38.5.2 (2023-02-02), servers running under Linux will need to have a relatively modern libstdc++ installed.  [https://www.mail-archive.com/csgo_servers@list.valvesoftware.com/msg14291.html See this mailing list entry for further details.]&lt;br /&gt;
* [[Introduction to SourceMod Plugins#Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported?|See the current state of Counter-Strike 2 here.]]&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead&lt;br /&gt;
| &amp;lt;code&amp;gt;222840&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* This is the one first-party game that requires a [https://www.metamodsource.net/?go=vdf custom VDF file for Metamod:Source].&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2&lt;br /&gt;
| &amp;lt;code&amp;gt;222860&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Half-Life 2: Deathmatch&lt;br /&gt;
| &amp;lt;code&amp;gt;232370&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;hl2mp&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| No More Room in Hell&lt;br /&gt;
| &amp;lt;code&amp;gt;317670&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;nmrih&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Zombie Panic! Source&lt;br /&gt;
| &amp;lt;code&amp;gt;17505&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;zps&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pirates, Vikings &amp;amp; Knights II&lt;br /&gt;
| &amp;lt;code&amp;gt;17575&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;pvkii&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For post-install server configuration, take a look at the [[../Game Server Configuration|Game Server Configuration]] page.&lt;br /&gt;
&lt;br /&gt;
= Installing Metamod:Source =&lt;br /&gt;
&lt;br /&gt;
Before you can install SourceMod on your server, you must first download and install Metamod:Source. Metamod:Source (MM:S) acts as a middleware for different Source Engine games, providing a unified interface for plugins to operate on the game.&lt;br /&gt;
&lt;br /&gt;
SourceMod itself is an MM:S plugin.&lt;br /&gt;
&lt;br /&gt;
# Download [http://www.metamodsource.net/ Metamod:Source]. In most cases, you want a stable release. Use the download package according to your server's operating system.&lt;br /&gt;
#* If the latest download is unavailable, go down the &amp;amp;quot;Latest 20 Builds&amp;amp;quot; until you get to one that is.&lt;br /&gt;
#* Again, make sure you're downloading the correct package for your server; if you're using a hosted instance, it may not be using the same operating system as your personal desktop.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
#* You may need to extract the archive on, or upload the contents to a remote server.&lt;br /&gt;
#** If you are on Windows, the recommended software to use for extracting Linux (&amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt;) archives is [https://www.7-zip.org/download.html 7-zip]; to upload files remotely via FTP, use [https://winscp.net/eng/index.php WinSCP].&lt;br /&gt;
#** If you are using a GSP, refer to their control panel.  Most provide FTP access, and some also allow for uploads directly via browser.&lt;br /&gt;
#** You should verify that the files were transmitted properly to the server; there have been reports of upload failures, zero-length files, and files that were mistakenly sent in text form and corrupted as a result.&lt;br /&gt;
# After installing, you should verify that the installation was successful by starting your server and running &amp;lt;tt&amp;gt;meta version&amp;lt;/tt&amp;gt;.  It should be treated as a known command at this stage.&lt;br /&gt;
#* Most games should work without further configuration, but if you find that MM:S isn't loading, you will want to [https://www.metamodsource.net/?go=vdf generate a custom VDF file].  Known games that require custom VDF files are:&lt;br /&gt;
#** Left 4 Dead 1&lt;br /&gt;
#** Third-party mods using the Source SDK base&lt;br /&gt;
#* Metamod:Source is known to fail to load on CS:GO servers running under Linux by default.  You will want to delete &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to the installation directory, plus read the information in the next bullet point.&lt;br /&gt;
#* If you are using a Linux server you have full control over, read over the [[User:Nosoop/Guide/Game Server Configuration#Platform-specific|Platform-specific setup]] information.&lt;br /&gt;
#* Additional diagnostic information about load failures is available under &amp;lt;tt&amp;gt;metamod-fatal.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Note|On server startup, you may see an error message &amp;lt;tt&amp;gt;Unable to load plugin &amp;quot;addons/metamod/bin/${platform}64/server&amp;quot;&amp;lt;/tt&amp;gt;.  This is normal behavior; the game server will always attempt to load both 32-bit and 64-bit binaries and fail on the one that doesn't match.  If you're sure that you're not running a 64-bit game server instance, you can delete &amp;lt;tt&amp;gt;addons/metamod_x64.vdf&amp;lt;/tt&amp;gt; to only load the 32-bit version, or the other way around.}}&lt;br /&gt;
&lt;br /&gt;
= Installing SourceMod =&lt;br /&gt;
&lt;br /&gt;
The following is mostly lifted from the [[Installing SourceMod]] page.&lt;br /&gt;
&lt;br /&gt;
# Download [https://www.sourcemod.net/ SourceMod]. Same as before; latest available stable release for your server's operating system.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If you plan on creating new plugins, you will also want to download SourceMod for your ''desktop'' operating system and extract the &amp;lt;code&amp;gt;addons/sourcemod/scripting/&amp;lt;/code&amp;gt; folder to a location on your computer.&lt;br /&gt;
&lt;br /&gt;
In the future, you may need to follow [[Upgrading SourceMod|these instructions to upgrade SourceMod]] on your server because of:&lt;br /&gt;
* game updates requiring SourceMod to be rebuilt against a new revision of the Source SDK&lt;br /&gt;
* plugins compiled against newer versions of SourceMod to take advantage of added functionality&lt;br /&gt;
&lt;br /&gt;
= Picking an IDE =&lt;br /&gt;
&lt;br /&gt;
Now that you have the dedicated game server, Metamod:Source, and SourceMod installed, you have most of the tools you need.&lt;br /&gt;
&lt;br /&gt;
If you've never done any programming, you'll need a text editor. It's completely possible to write code in plain old Notepad and invoke the compiler directly, but having a proper development environment makes it much easier to work with code.&lt;br /&gt;
&lt;br /&gt;
The following editors are known to have good support for SourceMod plugins:&lt;br /&gt;
&lt;br /&gt;
* Spider &amp;amp;mdash; recommended when starting out due to it being zero-install; once you are doing more than one-off plugins, move on to one of the non-web text editors&lt;br /&gt;
* Visual Studio Code (VSCode) &amp;amp;mdash; an increasingly popular choice combined with [https://marketplace.visualstudio.com/items?itemName=Sarrus.sourcepawn-vscode Sarrus's VSCode extension] [https://github.com/Sarrus1/sourcepawn-vscode (source code)]&lt;br /&gt;
* BasicPawn&lt;br /&gt;
* Notepad++&lt;br /&gt;
* SPEdit&lt;br /&gt;
* Sublime Text&lt;br /&gt;
&lt;br /&gt;
For more details on each editor and, if necessary, how to set it up for writing SourceMod plugins, look at the [[../Development Environments|Development Environments]] section of the guide.&lt;br /&gt;
&lt;br /&gt;
Once you've settled on a development environment, you can start learning how to create plugins &amp;amp;mdash; head over to the [[../Basics|Basics]] section of the guide to get started.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Client_Preferences_API_(SourceMod)&amp;diff=11681</id>
		<title>Client Preferences API (SourceMod)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Client_Preferences_API_(SourceMod)&amp;diff=11681"/>
		<updated>2024-01-01T00:33:07Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: Add note for multiple server handling&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The Client Preferences extension is bundled with SourceMod 1.1 and higher.  It lets you associate key/value pairs with clients who connect to servers.  This information persists across client connections, and therefore across map changes and server restarts, and even servers.&lt;br /&gt;
&lt;br /&gt;
{{note|For information to be synchronized across multiple servers, the extension must be configured on each server to access settings on a shared database (most commonly running MySQL).  By default, settings are saved in a standalone SQLite database unique to each server.}}&lt;br /&gt;
&lt;br /&gt;
==Cookies==&lt;br /&gt;
The basic unit of information is a &amp;quot;cookie&amp;quot;.  Cookies are unique keys registered by plugins, similar to ConVars.  Cookie names should always be reasonably descriptive to avoid clashes.&lt;br /&gt;
&lt;br /&gt;
Cookies are registered using RegClientCookie, usually in OnPluginStart.  Each cookie has a permission associated with it.  A &amp;quot;public&amp;quot; cookie means a client can see and change the value they have for this cookie.  A &amp;quot;protected&amp;quot; cookie means the client can only read it.  A &amp;quot;private&amp;quot; cookie is completely hidden from the user.&lt;br /&gt;
&lt;br /&gt;
The value of a cookie for a given client can be set using SetClientCookie, or retrieved using GetClientCookie.  The default value of a Cookie is an empty string.  Cookies are always stored as Strings, so if you want to store or retrieve cells/bools/Handles or Floats, you will need to convert them.  This can be done using the StringToInt, IntToString, StringToFloat, and FloatToString functions.&lt;br /&gt;
&lt;br /&gt;
==Asynchronicity==&lt;br /&gt;
When a client connects, their cookie information is retrieved asynchronously.  This means their data is not immediately available.  &lt;br /&gt;
&lt;br /&gt;
Use the AreClientCookiesCached native to detect whether a user's cookies are available yet.  If not, you will have to wait until OnClientCookiesCached is called for that client.  There is no guarantee that these will succeed.  For example, a player could connect and leave before a MySQL server responds.&lt;br /&gt;
&lt;br /&gt;
==Cookie Menus==&lt;br /&gt;
The original intent of Client Preferences was to abstract preferences.  For example, you might want to keep track whether a client wants to see a particular message or not.&lt;br /&gt;
&lt;br /&gt;
To assist this type of code, there is a unified &amp;quot;cookie menu&amp;quot; system.  The API is similar to TopMenus with the benefit that prefab menu formats are available.  Prefab cookie menus are created using SetCookiePrefabMenu.  The available prefabs are &amp;quot;Yes / No&amp;quot; and &amp;quot;On / Off&amp;quot;.  Fully custom menus can be created via SetCookieMenuItem.&lt;br /&gt;
&lt;br /&gt;
==Client Commands==&lt;br /&gt;
The &amp;lt;tt&amp;gt;sm_cookies&amp;lt;/tt&amp;gt; command allows users to view and set cookies.&lt;br /&gt;
The &amp;lt;tt&amp;gt;sm_settings&amp;lt;/tt&amp;gt; command displays the cookie menu.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;clientprefs&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Handle g_hMyCookie;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	g_hMyCookie = RegClientCookie(&amp;quot;myplugin_mycookie&amp;quot;, &amp;quot;MyPlugin MyCookie&amp;quot;, CookieAccess_Protected);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void SomeActionThatUsesCookie(int client)&lt;br /&gt;
{&lt;br /&gt;
	if (AreClientCookiesCached(client))&lt;br /&gt;
	{&lt;br /&gt;
		// Get cookie and add 1 to it&lt;br /&gt;
		char sCookieValue[12];&lt;br /&gt;
		GetClientCookie(client, g_hMyCookie, sCookieValue, sizeof(sCookieValue));&lt;br /&gt;
		int cookieValue = StringToInt(sCookieValue);&lt;br /&gt;
		cookieValue++;&lt;br /&gt;
		&lt;br /&gt;
		IntToString(cookieValue, sCookieValue, sizeof(sCookieValue));&lt;br /&gt;
&lt;br /&gt;
		SetClientCookie(client, g_hMyCookie, sCookieValue);&lt;br /&gt;
	}&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Development]]&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Compiling_SourceMod_Plugins&amp;diff=11679</id>
		<title>Compiling SourceMod Plugins</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Compiling_SourceMod_Plugins&amp;diff=11679"/>
		<updated>2023-11-25T16:27:07Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: Recommend Spider before the web compiler&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Okay, so you've read the [[Introduction to SourcePawn]] and [[Introduction to SourceMod Plugins]] and now you want to actually compile a plugin.&lt;br /&gt;
&lt;br /&gt;
The simplest way to compile a plugin that doesn't rely on any custom include files is using [https://spider.limetech.io/ Spider] or [http://www.sourcemod.net/compiler.php the web compiler].&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can use the executable compiler distributed with SourceMod. You can use this simply if you like compiling locally rather than using the web compiler. You have to use the local compiler if your plugin relies on custom include files. The compiler is included in the sourcemod/scripting/ folder of the [http://www.sourcemod.net/downloads.php SourceMod distribution].&lt;br /&gt;
&lt;br /&gt;
Windows: open up a command prompt (Start-&amp;gt;Run or WindowsKey+R, then &amp;quot;cmd&amp;quot;):&lt;br /&gt;
 cd &amp;lt;sourcemod&amp;gt;\scripting&lt;br /&gt;
 spcomp myplugin.sp&lt;br /&gt;
[http://www.computerhope.com/cdhlp.htm cd command reference]&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can simply drag the .sp file on top of spcomp.exe, which will compile the plugin for you.&lt;br /&gt;
&lt;br /&gt;
Linux: Depending on your Linux flavour you need to install the libc6 and libstdc++6 32bit libraries before you start to compile&lt;br /&gt;
&lt;br /&gt;
Example for Ubuntu:&lt;br /&gt;
  apt-get install libc6:i386 lib32stdc++6&lt;br /&gt;
&lt;br /&gt;
Then use:&lt;br /&gt;
 ./compile.sh myplugin.sp&lt;br /&gt;
&lt;br /&gt;
Now simply move the .smx (not .sp) file from sourcemod/scripting/compiled/ to the sourcemod/plugins/ folder.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' When compiling preexisting plugins it is easiest to move the included from the plugin source folder to the include folder in your sourcemod/scripting/include. Please see [[Spcomp_switches]] specifically the ''-i'' parameter for specifying a different folder for includes.&lt;br /&gt;
&lt;br /&gt;
[http://forums.alliedmods.net/showthread.php?t=52664 Reference Source]&lt;br /&gt;
&lt;br /&gt;
See Also: [http://forums.alliedmods.net/forumdisplay.php?f=107 Scripting Forum]&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11678</id>
		<title>User:Nosoop/Guide/Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11678"/>
		<updated>2023-11-16T07:58:14Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Installing Metamod:Source */ Reduce nesting in upload failure notes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section assumes that you're starting out with nothing besides a desktop computer, an internet connection, and a drive to program some SourceMod plugins. No programming experience; no problem.&lt;br /&gt;
&lt;br /&gt;
This page will walk you through manually installing the dedicated server software for your desired game, installing SourceMod, and selecting a text editor to use for development.&lt;br /&gt;
&lt;br /&gt;
There are a number of third-party tools that can automate most of these steps, but we'll stick to the first-party approach here to avoid abstractions from breaking under you.&lt;br /&gt;
&lt;br /&gt;
If you are using a third-party tool to manage your server installation, refer to the tool's documentation for their instructions, then skip to [[#Installing SourceMod|Installing SourceMod]] to download the scripting toolchain for your desktop operating system.&lt;br /&gt;
&lt;br /&gt;
= Installing the Server =&lt;br /&gt;
&lt;br /&gt;
{{note|&amp;lt;p&amp;gt;While officially unsupported, SourceMod may be loaded on a game client (the game you launch); the server a game client creates is known as a listen server. However, there are many behavioral quirks that can only be reproduced on a listen server, and you likely won't receive any solutions to those issues that aren't &amp;quot;use a dedicated server&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This guide does not provide instructions to load SourceMod on a game client. It's highly recommended to stick to installing SourceMod on dedicated game server instances to ensure that any plugins you write will have the correct behavior.&amp;lt;/p&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
To install the dedicated server software for the game of your choice, we will use &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt;. If a game server provider (GSP) is hosting the server for you, skip this step as your provider has already provided you with an installation; if you are using a self-hosted game server management panel, refer to the instructions for your software of choice to install your game server in place of this step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is Valve's command-line Steam client. It is used to install and update dedicated game servers.&lt;br /&gt;
&lt;br /&gt;
Refer to [https://developer.valvesoftware.com/wiki/SteamCMD the SteamCMD entry] in the Valve Developer Wiki for download instructions. This varies on the operating system you're running the software on; you can either work on your own desktop or have a hosted (physical or virtual) machine off-premises.&lt;br /&gt;
&lt;br /&gt;
Once &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is extracted, you will need to install a game. Continue reading the above wiki page to [https://developer.valvesoftware.com/wiki/SteamCMD#Running_SteamCMD run the application], [https://developer.valvesoftware.com/wiki/SteamCMD#SteamCMD_Login sign in (anonymously)], and [https://developer.valvesoftware.com/wiki/SteamCMD#Downloading_an_App download your game server].&lt;br /&gt;
&lt;br /&gt;
You will need the AppID of the game's dedicated server to install it; note that it is different from the game client AppIDs.  See the below table for that and additional related information for some of the supported games.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Dedicated Server Information&lt;br /&gt;
|-&lt;br /&gt;
! Game&lt;br /&gt;
! AppID&lt;br /&gt;
! Mod Directory&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Day of Defeat: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232290&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;dod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Team Fortress 2&lt;br /&gt;
| &amp;lt;code&amp;gt;232250&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;tf&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232330&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;cstrike&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Global Offensive&lt;br /&gt;
| &amp;lt;code&amp;gt;740&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* As of 1.38.5.2 (2023-02-02), servers running under Linux will need to have a relatively modern libstdc++ installed.  [https://www.mail-archive.com/csgo_servers@list.valvesoftware.com/msg14291.html See this mailing list entry for further details.]&lt;br /&gt;
* [[Introduction to SourceMod Plugins#Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported?|See the current state of Counter-Strike 2 here.]]&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead&lt;br /&gt;
| &amp;lt;code&amp;gt;222840&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* This is the one first-party game that requires a [https://www.metamodsource.net/?go=vdf custom VDF file for Metamod:Source].&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2&lt;br /&gt;
| &amp;lt;code&amp;gt;222860&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Half-Life 2: Deathmatch&lt;br /&gt;
| &amp;lt;code&amp;gt;232370&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;hl2mp&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| No More Room in Hell&lt;br /&gt;
| &amp;lt;code&amp;gt;317670&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;nmrih&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Zombie Panic! Source&lt;br /&gt;
| &amp;lt;code&amp;gt;17505&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;zps&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pirates, Vikings &amp;amp; Knights II&lt;br /&gt;
| &amp;lt;code&amp;gt;17575&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;pvkii&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For post-install server configuration, take a look at the [[../Game Server Configuration|Game Server Configuration]] page.&lt;br /&gt;
&lt;br /&gt;
= Installing Metamod:Source =&lt;br /&gt;
&lt;br /&gt;
Before you can install SourceMod on your server, you must first download and install Metamod:Source. Metamod:Source (MM:S) acts as a middleware for different Source Engine games, providing a unified interface for plugins to operate on the game.&lt;br /&gt;
&lt;br /&gt;
SourceMod itself is an MM:S plugin.&lt;br /&gt;
&lt;br /&gt;
# Download [http://www.metamodsource.net/ Metamod:Source]. In most cases, you want a stable release. Use the download package according to your server's operating system.&lt;br /&gt;
#* If the latest download is unavailable, go down the &amp;amp;quot;Latest 20 Builds&amp;amp;quot; until you get to one that is.&lt;br /&gt;
#* Again, make sure you're downloading the correct package for your server; if you're using a hosted instance, it may not be using the same operating system as your personal desktop.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
#* You may need to extract the archive on, or upload the contents to a remote server.&lt;br /&gt;
#** If you are on Windows, the recommended software to use for extracting Linux (&amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt;) archives is [https://www.7-zip.org/download.html 7-zip]; to upload files remotely via FTP, use [https://winscp.net/eng/index.php WinSCP].&lt;br /&gt;
#** If you are using a GSP, refer to their control panel.  Most provide FTP access, and some also allow for uploads directly via browser.&lt;br /&gt;
#** You should verify that the files were transmitted properly to the server; there have been reports of upload failures, zero-length files, and files that were mistakenly sent in text form and corrupted as a result.&lt;br /&gt;
# After installing, you should verify that the installation was successful by starting your server and running &amp;lt;tt&amp;gt;meta version&amp;lt;/tt&amp;gt;.  It should be treated as a known command at this stage.&lt;br /&gt;
#* Most games should work without further configuration, but if you find that MM:S isn't loading, you will want to [https://www.metamodsource.net/?go=vdf generate a custom VDF file].  Known games that require custom VDF files are:&lt;br /&gt;
#** Left 4 Dead 1&lt;br /&gt;
#** Third-party mods using the Source SDK base&lt;br /&gt;
#* Metamod:Source is known to fail to load on CS:GO servers running under Linux by default.  You will want to delete &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to the installation directory, plus read the information in the next bullet point.&lt;br /&gt;
#* If you are using a Linux server you have full control over, read over the [[User:Nosoop/Guide/Game Server Configuration#Platform-specific|Platform-specific setup]] information.&lt;br /&gt;
#* Additional diagnostic information about load failures is available under &amp;lt;tt&amp;gt;metamod-fatal.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Note|On server startup, you may see an error message &amp;lt;tt&amp;gt;Unable to load plugin &amp;quot;addons/metamod/bin/${platform}64/server&amp;quot;&amp;lt;/tt&amp;gt;.  This is normal behavior; the game server will always attempt to load both 32-bit and 64-bit binaries and fail on the one that doesn't match.  If you're sure that you're not running a 64-bit game server instance, you can delete &amp;lt;tt&amp;gt;addons/metamod_x64.vdf&amp;lt;/tt&amp;gt; to only load the 32-bit version, or the other way around.}}&lt;br /&gt;
&lt;br /&gt;
= Installing SourceMod =&lt;br /&gt;
&lt;br /&gt;
The following is mostly lifted from the [[Installing SourceMod]] page.&lt;br /&gt;
&lt;br /&gt;
# Download [https://www.sourcemod.net/ SourceMod]. Same as before; latest available stable release for your server's operating system.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If you plan on creating new plugins, you will also want to download SourceMod for your ''desktop'' operating system and extract the &amp;lt;code&amp;gt;addons/sourcemod/scripting/&amp;lt;/code&amp;gt; folder to a location on your computer.&lt;br /&gt;
&lt;br /&gt;
In the future, you may need to follow [[Upgrading SourceMod|these instructions to upgrade SourceMod]] on your server because of:&lt;br /&gt;
* game updates requiring SourceMod to be rebuilt against a new revision of the Source SDK&lt;br /&gt;
* plugins compiled against newer versions of SourceMod to take advantage of added functionality&lt;br /&gt;
&lt;br /&gt;
= Picking an IDE =&lt;br /&gt;
&lt;br /&gt;
Now that you have the dedicated game server, Metamod:Source, and SourceMod installed, you have most of the tools you need.&lt;br /&gt;
&lt;br /&gt;
If you've never done any programming, you'll need a text editor. It's completely possible to write code in plain old Notepad and invoke the compiler directly, but having a proper development environment makes it much easier to work with code.&lt;br /&gt;
&lt;br /&gt;
The following editors are known to have good support for SourceMod plugins:&lt;br /&gt;
&lt;br /&gt;
* Spider &amp;amp;mdash; recommended when starting out due to it being zero-install; once you are doing more than one-off plugins, move on to one of the non-web text editors&lt;br /&gt;
* Visual Studio Code (VSCode) &amp;amp;mdash; an increasingly popular choice combined with [https://marketplace.visualstudio.com/items?itemName=Sarrus.sourcepawn-vscode Sarrus's VSCode extension] [https://github.com/Sarrus1/sourcepawn-vscode (source code)]&lt;br /&gt;
* BasicPawn&lt;br /&gt;
* Notepad++&lt;br /&gt;
* SPEdit&lt;br /&gt;
* Sublime Text&lt;br /&gt;
&lt;br /&gt;
For more details on each editor and, if necessary, how to set it up for writing SourceMod plugins, look at the [[../Development Environments|Development Environments]] section of the guide.&lt;br /&gt;
&lt;br /&gt;
Once you've settled on a development environment, you can start learning how to create plugins &amp;amp;mdash; head over to the [[../Basics|Basics]] section of the guide to get started.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11677</id>
		<title>User:Nosoop/Guide/Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11677"/>
		<updated>2023-11-16T07:57:46Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Installing Metamod:Source */ Add note on potential issue with remote file uploads&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section assumes that you're starting out with nothing besides a desktop computer, an internet connection, and a drive to program some SourceMod plugins. No programming experience; no problem.&lt;br /&gt;
&lt;br /&gt;
This page will walk you through manually installing the dedicated server software for your desired game, installing SourceMod, and selecting a text editor to use for development.&lt;br /&gt;
&lt;br /&gt;
There are a number of third-party tools that can automate most of these steps, but we'll stick to the first-party approach here to avoid abstractions from breaking under you.&lt;br /&gt;
&lt;br /&gt;
If you are using a third-party tool to manage your server installation, refer to the tool's documentation for their instructions, then skip to [[#Installing SourceMod|Installing SourceMod]] to download the scripting toolchain for your desktop operating system.&lt;br /&gt;
&lt;br /&gt;
= Installing the Server =&lt;br /&gt;
&lt;br /&gt;
{{note|&amp;lt;p&amp;gt;While officially unsupported, SourceMod may be loaded on a game client (the game you launch); the server a game client creates is known as a listen server. However, there are many behavioral quirks that can only be reproduced on a listen server, and you likely won't receive any solutions to those issues that aren't &amp;quot;use a dedicated server&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This guide does not provide instructions to load SourceMod on a game client. It's highly recommended to stick to installing SourceMod on dedicated game server instances to ensure that any plugins you write will have the correct behavior.&amp;lt;/p&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
To install the dedicated server software for the game of your choice, we will use &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt;. If a game server provider (GSP) is hosting the server for you, skip this step as your provider has already provided you with an installation; if you are using a self-hosted game server management panel, refer to the instructions for your software of choice to install your game server in place of this step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is Valve's command-line Steam client. It is used to install and update dedicated game servers.&lt;br /&gt;
&lt;br /&gt;
Refer to [https://developer.valvesoftware.com/wiki/SteamCMD the SteamCMD entry] in the Valve Developer Wiki for download instructions. This varies on the operating system you're running the software on; you can either work on your own desktop or have a hosted (physical or virtual) machine off-premises.&lt;br /&gt;
&lt;br /&gt;
Once &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is extracted, you will need to install a game. Continue reading the above wiki page to [https://developer.valvesoftware.com/wiki/SteamCMD#Running_SteamCMD run the application], [https://developer.valvesoftware.com/wiki/SteamCMD#SteamCMD_Login sign in (anonymously)], and [https://developer.valvesoftware.com/wiki/SteamCMD#Downloading_an_App download your game server].&lt;br /&gt;
&lt;br /&gt;
You will need the AppID of the game's dedicated server to install it; note that it is different from the game client AppIDs.  See the below table for that and additional related information for some of the supported games.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Dedicated Server Information&lt;br /&gt;
|-&lt;br /&gt;
! Game&lt;br /&gt;
! AppID&lt;br /&gt;
! Mod Directory&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Day of Defeat: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232290&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;dod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Team Fortress 2&lt;br /&gt;
| &amp;lt;code&amp;gt;232250&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;tf&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232330&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;cstrike&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Global Offensive&lt;br /&gt;
| &amp;lt;code&amp;gt;740&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* As of 1.38.5.2 (2023-02-02), servers running under Linux will need to have a relatively modern libstdc++ installed.  [https://www.mail-archive.com/csgo_servers@list.valvesoftware.com/msg14291.html See this mailing list entry for further details.]&lt;br /&gt;
* [[Introduction to SourceMod Plugins#Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported?|See the current state of Counter-Strike 2 here.]]&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead&lt;br /&gt;
| &amp;lt;code&amp;gt;222840&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* This is the one first-party game that requires a [https://www.metamodsource.net/?go=vdf custom VDF file for Metamod:Source].&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2&lt;br /&gt;
| &amp;lt;code&amp;gt;222860&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Half-Life 2: Deathmatch&lt;br /&gt;
| &amp;lt;code&amp;gt;232370&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;hl2mp&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| No More Room in Hell&lt;br /&gt;
| &amp;lt;code&amp;gt;317670&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;nmrih&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Zombie Panic! Source&lt;br /&gt;
| &amp;lt;code&amp;gt;17505&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;zps&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pirates, Vikings &amp;amp; Knights II&lt;br /&gt;
| &amp;lt;code&amp;gt;17575&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;pvkii&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For post-install server configuration, take a look at the [[../Game Server Configuration|Game Server Configuration]] page.&lt;br /&gt;
&lt;br /&gt;
= Installing Metamod:Source =&lt;br /&gt;
&lt;br /&gt;
Before you can install SourceMod on your server, you must first download and install Metamod:Source. Metamod:Source (MM:S) acts as a middleware for different Source Engine games, providing a unified interface for plugins to operate on the game.&lt;br /&gt;
&lt;br /&gt;
SourceMod itself is an MM:S plugin.&lt;br /&gt;
&lt;br /&gt;
# Download [http://www.metamodsource.net/ Metamod:Source]. In most cases, you want a stable release. Use the download package according to your server's operating system.&lt;br /&gt;
#* If the latest download is unavailable, go down the &amp;amp;quot;Latest 20 Builds&amp;amp;quot; until you get to one that is.&lt;br /&gt;
#* Again, make sure you're downloading the correct package for your server; if you're using a hosted instance, it may not be using the same operating system as your personal desktop.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
#* You may need to extract the archive on, or upload the contents to a remote server.&lt;br /&gt;
#** If you are on Windows, the recommended software to use for extracting Linux (&amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt;) archives is [https://www.7-zip.org/download.html 7-zip]; to upload files remotely via FTP, use [https://winscp.net/eng/index.php WinSCP].&lt;br /&gt;
#** If you are using a GSP, refer to their control panel.  Most provide FTP access, and some also allow for uploads directly via browser.&lt;br /&gt;
#*** You should verify that the files were transmitted properly to the server; there have been reports of upload failures, zero-length files, and files that were mistakenly sent in text form and corrupted as a result.&lt;br /&gt;
# After installing, you should verify that the installation was successful by starting your server and running &amp;lt;tt&amp;gt;meta version&amp;lt;/tt&amp;gt;.  It should be treated as a known command at this stage.&lt;br /&gt;
#* Most games should work without further configuration, but if you find that MM:S isn't loading, you will want to [https://www.metamodsource.net/?go=vdf generate a custom VDF file].  Known games that require custom VDF files are:&lt;br /&gt;
#** Left 4 Dead 1&lt;br /&gt;
#** Third-party mods using the Source SDK base&lt;br /&gt;
#* Metamod:Source is known to fail to load on CS:GO servers running under Linux by default.  You will want to delete &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to the installation directory, plus read the information in the next bullet point.&lt;br /&gt;
#* If you are using a Linux server you have full control over, read over the [[User:Nosoop/Guide/Game Server Configuration#Platform-specific|Platform-specific setup]] information.&lt;br /&gt;
#* Additional diagnostic information about load failures is available under &amp;lt;tt&amp;gt;metamod-fatal.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Note|On server startup, you may see an error message &amp;lt;tt&amp;gt;Unable to load plugin &amp;quot;addons/metamod/bin/${platform}64/server&amp;quot;&amp;lt;/tt&amp;gt;.  This is normal behavior; the game server will always attempt to load both 32-bit and 64-bit binaries and fail on the one that doesn't match.  If you're sure that you're not running a 64-bit game server instance, you can delete &amp;lt;tt&amp;gt;addons/metamod_x64.vdf&amp;lt;/tt&amp;gt; to only load the 32-bit version, or the other way around.}}&lt;br /&gt;
&lt;br /&gt;
= Installing SourceMod =&lt;br /&gt;
&lt;br /&gt;
The following is mostly lifted from the [[Installing SourceMod]] page.&lt;br /&gt;
&lt;br /&gt;
# Download [https://www.sourcemod.net/ SourceMod]. Same as before; latest available stable release for your server's operating system.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If you plan on creating new plugins, you will also want to download SourceMod for your ''desktop'' operating system and extract the &amp;lt;code&amp;gt;addons/sourcemod/scripting/&amp;lt;/code&amp;gt; folder to a location on your computer.&lt;br /&gt;
&lt;br /&gt;
In the future, you may need to follow [[Upgrading SourceMod|these instructions to upgrade SourceMod]] on your server because of:&lt;br /&gt;
* game updates requiring SourceMod to be rebuilt against a new revision of the Source SDK&lt;br /&gt;
* plugins compiled against newer versions of SourceMod to take advantage of added functionality&lt;br /&gt;
&lt;br /&gt;
= Picking an IDE =&lt;br /&gt;
&lt;br /&gt;
Now that you have the dedicated game server, Metamod:Source, and SourceMod installed, you have most of the tools you need.&lt;br /&gt;
&lt;br /&gt;
If you've never done any programming, you'll need a text editor. It's completely possible to write code in plain old Notepad and invoke the compiler directly, but having a proper development environment makes it much easier to work with code.&lt;br /&gt;
&lt;br /&gt;
The following editors are known to have good support for SourceMod plugins:&lt;br /&gt;
&lt;br /&gt;
* Spider &amp;amp;mdash; recommended when starting out due to it being zero-install; once you are doing more than one-off plugins, move on to one of the non-web text editors&lt;br /&gt;
* Visual Studio Code (VSCode) &amp;amp;mdash; an increasingly popular choice combined with [https://marketplace.visualstudio.com/items?itemName=Sarrus.sourcepawn-vscode Sarrus's VSCode extension] [https://github.com/Sarrus1/sourcepawn-vscode (source code)]&lt;br /&gt;
* BasicPawn&lt;br /&gt;
* Notepad++&lt;br /&gt;
* SPEdit&lt;br /&gt;
* Sublime Text&lt;br /&gt;
&lt;br /&gt;
For more details on each editor and, if necessary, how to set it up for writing SourceMod plugins, look at the [[../Development Environments|Development Environments]] section of the guide.&lt;br /&gt;
&lt;br /&gt;
Once you've settled on a development environment, you can start learning how to create plugins &amp;amp;mdash; head over to the [[../Basics|Basics]] section of the guide to get started.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11676</id>
		<title>User:Nosoop/Guide/Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11676"/>
		<updated>2023-11-10T16:25:23Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Picking an IDE */ Directly link to Sarrus's extension&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section assumes that you're starting out with nothing besides a desktop computer, an internet connection, and a drive to program some SourceMod plugins. No programming experience; no problem.&lt;br /&gt;
&lt;br /&gt;
This page will walk you through manually installing the dedicated server software for your desired game, installing SourceMod, and selecting a text editor to use for development.&lt;br /&gt;
&lt;br /&gt;
There are a number of third-party tools that can automate most of these steps, but we'll stick to the first-party approach here to avoid abstractions from breaking under you.&lt;br /&gt;
&lt;br /&gt;
If you are using a third-party tool to manage your server installation, refer to the tool's documentation for their instructions, then skip to [[#Installing SourceMod|Installing SourceMod]] to download the scripting toolchain for your desktop operating system.&lt;br /&gt;
&lt;br /&gt;
= Installing the Server =&lt;br /&gt;
&lt;br /&gt;
{{note|&amp;lt;p&amp;gt;While officially unsupported, SourceMod may be loaded on a game client (the game you launch); the server a game client creates is known as a listen server. However, there are many behavioral quirks that can only be reproduced on a listen server, and you likely won't receive any solutions to those issues that aren't &amp;quot;use a dedicated server&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This guide does not provide instructions to load SourceMod on a game client. It's highly recommended to stick to installing SourceMod on dedicated game server instances to ensure that any plugins you write will have the correct behavior.&amp;lt;/p&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
To install the dedicated server software for the game of your choice, we will use &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt;. If a game server provider (GSP) is hosting the server for you, skip this step as your provider has already provided you with an installation; if you are using a self-hosted game server management panel, refer to the instructions for your software of choice to install your game server in place of this step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is Valve's command-line Steam client. It is used to install and update dedicated game servers.&lt;br /&gt;
&lt;br /&gt;
Refer to [https://developer.valvesoftware.com/wiki/SteamCMD the SteamCMD entry] in the Valve Developer Wiki for download instructions. This varies on the operating system you're running the software on; you can either work on your own desktop or have a hosted (physical or virtual) machine off-premises.&lt;br /&gt;
&lt;br /&gt;
Once &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is extracted, you will need to install a game. Continue reading the above wiki page to [https://developer.valvesoftware.com/wiki/SteamCMD#Running_SteamCMD run the application], [https://developer.valvesoftware.com/wiki/SteamCMD#SteamCMD_Login sign in (anonymously)], and [https://developer.valvesoftware.com/wiki/SteamCMD#Downloading_an_App download your game server].&lt;br /&gt;
&lt;br /&gt;
You will need the AppID of the game's dedicated server to install it; note that it is different from the game client AppIDs.  See the below table for that and additional related information for some of the supported games.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Dedicated Server Information&lt;br /&gt;
|-&lt;br /&gt;
! Game&lt;br /&gt;
! AppID&lt;br /&gt;
! Mod Directory&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Day of Defeat: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232290&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;dod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Team Fortress 2&lt;br /&gt;
| &amp;lt;code&amp;gt;232250&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;tf&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232330&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;cstrike&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Global Offensive&lt;br /&gt;
| &amp;lt;code&amp;gt;740&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* As of 1.38.5.2 (2023-02-02), servers running under Linux will need to have a relatively modern libstdc++ installed.  [https://www.mail-archive.com/csgo_servers@list.valvesoftware.com/msg14291.html See this mailing list entry for further details.]&lt;br /&gt;
* [[Introduction to SourceMod Plugins#Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported?|See the current state of Counter-Strike 2 here.]]&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead&lt;br /&gt;
| &amp;lt;code&amp;gt;222840&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* This is the one first-party game that requires a [https://www.metamodsource.net/?go=vdf custom VDF file for Metamod:Source].&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2&lt;br /&gt;
| &amp;lt;code&amp;gt;222860&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Half-Life 2: Deathmatch&lt;br /&gt;
| &amp;lt;code&amp;gt;232370&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;hl2mp&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| No More Room in Hell&lt;br /&gt;
| &amp;lt;code&amp;gt;317670&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;nmrih&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Zombie Panic! Source&lt;br /&gt;
| &amp;lt;code&amp;gt;17505&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;zps&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pirates, Vikings &amp;amp; Knights II&lt;br /&gt;
| &amp;lt;code&amp;gt;17575&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;pvkii&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For post-install server configuration, take a look at the [[../Game Server Configuration|Game Server Configuration]] page.&lt;br /&gt;
&lt;br /&gt;
= Installing Metamod:Source =&lt;br /&gt;
&lt;br /&gt;
Before you can install SourceMod on your server, you must first download and install Metamod:Source. Metamod:Source (MM:S) acts as a middleware for different Source Engine games, providing a unified interface for plugins to operate on the game.&lt;br /&gt;
&lt;br /&gt;
SourceMod itself is an MM:S plugin.&lt;br /&gt;
&lt;br /&gt;
# Download [http://www.metamodsource.net/ Metamod:Source]. In most cases, you want a stable release. Use the download package according to your server's operating system.&lt;br /&gt;
#* If the latest download is unavailable, go down the &amp;amp;quot;Latest 20 Builds&amp;amp;quot; until you get to one that is.&lt;br /&gt;
#* Again, make sure you're downloading the correct package for your server; if you're using a hosted instance, it may not be using the same operating system as your personal desktop.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
#* You may need to extract the archive on, or upload the contents to a remote server.&lt;br /&gt;
#** If you are on Windows, the recommended software to use for extracting Linux (&amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt;) archives is [https://www.7-zip.org/download.html 7-zip]; to upload files remotely via FTP, use [https://winscp.net/eng/index.php WinSCP].&lt;br /&gt;
#** If you are using a GSP, refer to their control panel.  Most provide FTP access, and some also allow for uploads directly via browser.&lt;br /&gt;
# You may want to verify that the installation was successful by starting your server and running &amp;lt;tt&amp;gt;meta version&amp;lt;/tt&amp;gt;.  It should be treated as a known command at this stage.&lt;br /&gt;
#* Most games should work without further configuration, but if you find that MM:S isn't loading, you will want to [https://www.metamodsource.net/?go=vdf generate a custom VDF file].  Known games that require custom VDF files are:&lt;br /&gt;
#** Left 4 Dead 1&lt;br /&gt;
#** Third-party mods using the Source SDK base&lt;br /&gt;
#* Metamod:Source is known to fail to load on CS:GO servers running under Linux by default.  You will want to delete &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to the installation directory, plus read the information in the next bullet point.&lt;br /&gt;
#* If you are using a Linux server you have full control over, read over the [[User:Nosoop/Guide/Game Server Configuration#Platform-specific|Platform-specific setup]] information.&lt;br /&gt;
#* Additional diagnostic information about load failures is available under &amp;lt;tt&amp;gt;metamod-fatal.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Note|On server startup, you may see an error message &amp;lt;tt&amp;gt;Unable to load plugin &amp;quot;addons/metamod/bin/${platform}64/server&amp;quot;&amp;lt;/tt&amp;gt;.  This is normal behavior; the game server will always attempt to load both 32-bit and 64-bit binaries and fail on the one that doesn't match.  If you're sure that you're not running a 64-bit game server instance, you can delete &amp;lt;tt&amp;gt;addons/metamod_x64.vdf&amp;lt;/tt&amp;gt; to only load the 32-bit version, or the other way around.}}&lt;br /&gt;
&lt;br /&gt;
= Installing SourceMod =&lt;br /&gt;
&lt;br /&gt;
The following is mostly lifted from the [[Installing SourceMod]] page.&lt;br /&gt;
&lt;br /&gt;
# Download [https://www.sourcemod.net/ SourceMod]. Same as before; latest available stable release for your server's operating system.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If you plan on creating new plugins, you will also want to download SourceMod for your ''desktop'' operating system and extract the &amp;lt;code&amp;gt;addons/sourcemod/scripting/&amp;lt;/code&amp;gt; folder to a location on your computer.&lt;br /&gt;
&lt;br /&gt;
In the future, you may need to follow [[Upgrading SourceMod|these instructions to upgrade SourceMod]] on your server because of:&lt;br /&gt;
* game updates requiring SourceMod to be rebuilt against a new revision of the Source SDK&lt;br /&gt;
* plugins compiled against newer versions of SourceMod to take advantage of added functionality&lt;br /&gt;
&lt;br /&gt;
= Picking an IDE =&lt;br /&gt;
&lt;br /&gt;
Now that you have the dedicated game server, Metamod:Source, and SourceMod installed, you have most of the tools you need.&lt;br /&gt;
&lt;br /&gt;
If you've never done any programming, you'll need a text editor. It's completely possible to write code in plain old Notepad and invoke the compiler directly, but having a proper development environment makes it much easier to work with code.&lt;br /&gt;
&lt;br /&gt;
The following editors are known to have good support for SourceMod plugins:&lt;br /&gt;
&lt;br /&gt;
* Spider &amp;amp;mdash; recommended when starting out due to it being zero-install; once you are doing more than one-off plugins, move on to one of the non-web text editors&lt;br /&gt;
* Visual Studio Code (VSCode) &amp;amp;mdash; an increasingly popular choice combined with [https://marketplace.visualstudio.com/items?itemName=Sarrus.sourcepawn-vscode Sarrus's VSCode extension] [https://github.com/Sarrus1/sourcepawn-vscode (source code)]&lt;br /&gt;
* BasicPawn&lt;br /&gt;
* Notepad++&lt;br /&gt;
* SPEdit&lt;br /&gt;
* Sublime Text&lt;br /&gt;
&lt;br /&gt;
For more details on each editor and, if necessary, how to set it up for writing SourceMod plugins, look at the [[../Development Environments|Development Environments]] section of the guide.&lt;br /&gt;
&lt;br /&gt;
Once you've settled on a development environment, you can start learning how to create plugins &amp;amp;mdash; head over to the [[../Basics|Basics]] section of the guide to get started.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Entity_Lumps_(SourceMod_Scripting)&amp;diff=11663</id>
		<title>Entity Lumps (SourceMod Scripting)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Entity_Lumps_(SourceMod_Scripting)&amp;diff=11663"/>
		<updated>2023-10-09T05:03:44Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: Add notes on release and describe what the entity lump is&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine maps store entity data in [https://developer.valvesoftware.com/wiki/Source_BSP_File_Format#Entity an entity lump], which is a plain text file containing a list of key / value pairs describing each entity.&lt;br /&gt;
&lt;br /&gt;
SourceMod implements functionality to manipulate this data in &amp;lt;tt&amp;gt;entitylump.inc&amp;lt;/tt&amp;gt;.  This functionality was added to the development branch in 1.12.0.6922, then backported to the stable branch in 1.11.0.6919 (after its release).&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
The global EntityLump methodmap contains functions to access individual entity entries.  Below is an example lump that will be used throughout the rest of this page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
&amp;quot;world_maxs&amp;quot; &amp;quot;2624 4720 1728&amp;quot;&lt;br /&gt;
&amp;quot;world_mins&amp;quot; &amp;quot;-3536 -4720 -560&amp;quot;&lt;br /&gt;
&amp;quot;skyname&amp;quot; &amp;quot;sky_tf2_04&amp;quot;&lt;br /&gt;
&amp;quot;minoccluderarea_x360&amp;quot; &amp;quot;110&amp;quot;&lt;br /&gt;
&amp;quot;maxpropscreenwidth&amp;quot; &amp;quot;-1&amp;quot;&lt;br /&gt;
&amp;quot;detailvbsp&amp;quot; &amp;quot;detail_2fort.vbsp&amp;quot;&lt;br /&gt;
&amp;quot;detailmaterial&amp;quot; &amp;quot;detail/detailsprites_2fort&amp;quot;&lt;br /&gt;
&amp;quot;classname&amp;quot; &amp;quot;worldspawn&amp;quot;&lt;br /&gt;
&amp;quot;mapversion&amp;quot; &amp;quot;4067&amp;quot;&lt;br /&gt;
&amp;quot;hammerid&amp;quot; &amp;quot;4396&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;origin&amp;quot; &amp;quot;212.201 1784.53 259.256&amp;quot;&lt;br /&gt;
&amp;quot;fademindist&amp;quot; &amp;quot;-1&amp;quot;&lt;br /&gt;
&amp;quot;AutoMaterialize&amp;quot; &amp;quot;1&amp;quot;&lt;br /&gt;
&amp;quot;angles&amp;quot; &amp;quot;0 180 0&amp;quot;&lt;br /&gt;
&amp;quot;classname&amp;quot; &amp;quot;item_ammopack_small&amp;quot;&lt;br /&gt;
&amp;quot;hammerid&amp;quot; &amp;quot;5314720&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
{&lt;br /&gt;
&amp;quot;origin&amp;quot; &amp;quot;-48 84 617&amp;quot;&lt;br /&gt;
&amp;quot;spawnflags&amp;quot; &amp;quot;1&amp;quot;&lt;br /&gt;
&amp;quot;classname&amp;quot; &amp;quot;logic_auto&amp;quot;&lt;br /&gt;
&amp;quot;hammerid&amp;quot; &amp;quot;741865&amp;quot;&lt;br /&gt;
&amp;quot;OnMapSpawn&amp;quot; &amp;quot;tonemap_global,SetAutoExposureMin,.8,0,-1&amp;quot;&lt;br /&gt;
&amp;quot;OnMapSpawn&amp;quot; &amp;quot;tonemap_global,SetAutoExposureMax,1.1,0,-1&amp;quot;&lt;br /&gt;
&amp;quot;OnMapSpawn&amp;quot; &amp;quot;tonemap_global,SetBloomScale,.5,0,-1&amp;quot;&lt;br /&gt;
&amp;quot;OnMapSpawn&amp;quot; &amp;quot;tf_gamerules,SetBlueTeamGoalString,#2fort_blue_setup_goal,0,-1&amp;quot;&lt;br /&gt;
&amp;quot;OnMapSpawn&amp;quot; &amp;quot;tf_gamerules,SetRedTeamGoalString,#2fort_red_setup_goal,0,-1&amp;quot;&lt;br /&gt;
&amp;quot;OnMapSpawn&amp;quot; &amp;quot;tf_gamerules,SetStalemateOnTimelimit,1,0,-1&amp;quot;&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Plugins must modify the entity lump during the &amp;lt;tt&amp;gt;OnMapInit&amp;lt;/tt&amp;gt; forward.  Attempting to use non-read operations (such as update, insert, append, and erase) outside of that forward will raise a runtime error.&lt;br /&gt;
&lt;br /&gt;
=Entity Lump=&lt;br /&gt;
&lt;br /&gt;
The global &amp;lt;tt&amp;gt;EntityLump&amp;lt;/tt&amp;gt; behaves like an {{SourceMod API|file=adt_array|function=ArrayList}}; to get a specific entity lump entry you must call its &amp;lt;tt&amp;gt;Get&amp;lt;/tt&amp;gt; function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
// get the worldspawn entity from the list&lt;br /&gt;
EntityLumpEntry entry = EntityLump.Get(0);&lt;br /&gt;
&lt;br /&gt;
// release our handle to it when we are done&lt;br /&gt;
delete entry;&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don't know where your desired entity is, you must iterate over the list:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
for (int i, n = EntityLump.Length(); i &amp;lt; n; i++)&lt;br /&gt;
{&lt;br /&gt;
	EntityLumpEntry entry = EntityLump.Get(i);&lt;br /&gt;
	if (entry.FindKey(&amp;quot;AutoMaterialize&amp;quot;) != -1)&lt;br /&gt;
	{&lt;br /&gt;
		// this item has at least one 'AutoMaterialize' key&lt;br /&gt;
	}&lt;br /&gt;
	delete entry;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Entity Lump Entry=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;EntityLumpEntry&amp;lt;/tt&amp;gt; handles contains a list of key / value pairs.&lt;br /&gt;
&lt;br /&gt;
You can modify an entry's values:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
// get the item_ammopack_small entity from the list&lt;br /&gt;
EntityLumpEntry entry = EntityLump.Get(1);&lt;br /&gt;
&lt;br /&gt;
// find the 'classname' key in the list, then modify it&lt;br /&gt;
int icname = entry.FindKey(&amp;quot;classname&amp;quot;);&lt;br /&gt;
if (icname != -1)&lt;br /&gt;
{&lt;br /&gt;
	// keep the name as 'classname', but change the value to 'item_ammopack_full'&lt;br /&gt;
	entry.Update(icname, NULL_STRING, &amp;quot;item_ammopack_full&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
delete entry;&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Keys do not have a one-to-one mapping with values; there may be duplicates.  You can iterate over the available key / value pairs matching the key name with &amp;lt;tt&amp;gt;EntityLumpEntry.GetNextKey()&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
// get the 'logic_auto' from the list&lt;br /&gt;
EntityLumpEntry entry = EntityLump.Get(2);&lt;br /&gt;
char outputString[256];&lt;br /&gt;
for (int i = -1; (i = entry.GetNextKey(&amp;quot;OnMapSpawn&amp;quot;, outputString, sizeof(outputString), i)) != -1;)&lt;br /&gt;
{&lt;br /&gt;
	// print all of the logic_auto's OnMapSpawn outputs&lt;br /&gt;
	LogMessage(&amp;quot;OnMapSpawn output: %s&amp;quot;, outputString);&lt;br /&gt;
}&lt;br /&gt;
delete entry;&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11662</id>
		<title>User:Nosoop/Guide/Game Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11662"/>
		<updated>2023-09-22T03:45:13Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* General */ Add section on profiling&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine games often differ in configuration; here are some basic suggestions on how to set them up for either testing or production use.&lt;br /&gt;
&lt;br /&gt;
= General =&lt;br /&gt;
&lt;br /&gt;
The following section(s) apply to most, if not all games.&lt;br /&gt;
&lt;br /&gt;
== Fast Downloads ==&lt;br /&gt;
&lt;br /&gt;
The Source Engine normally provides downloads over the same channel as gameplay, which is rather slow.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;quot;Fast&amp;amp;quot; downloads are downloads served out-of-band over HTTP, and as such you will need to have a web (HTTP) server up and running to take advantage of this functionality.  This is highly recommended if you are running a server with any amount of custom content that a player needs to download (models, sounds, maps).&lt;br /&gt;
&lt;br /&gt;
If you're using a game server provider, you may already have access to a web server for fast download purposes; check with your provider to confirm.&lt;br /&gt;
&lt;br /&gt;
Examples of web servers include: [https://www.nginx.com/ nginx], [https://caddyserver.com/ Caddy], [https://httpd.apache.org/ Apache], [https://www.rejetto.com/hfs/ HFS], and [https://en.wikipedia.org/wiki/Comparison_of_web_server_software many others] (and many more not included in that list).&lt;br /&gt;
&lt;br /&gt;
Once you have an HTTP server running, configure &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_downloadurl &amp;amp;quot;http://{your_server_location}/{path}&amp;amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The URL must be quoted, as &amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; is treated as the start of a comment and if left unquoted, the rest of the line will be ignored.  Do not include a trailing slash &amp;amp;mdash; the game client adds one when making the request; web servers are not guaranteed to collapse double slashes in the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;{path}&amp;lt;/tt&amp;gt; should be the path on your server that would translate to the root of your game server.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a file &amp;lt;tt&amp;gt;sound/my_server/fart.mp3&amp;lt;/tt&amp;gt; and an &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;, the client will request &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads/sound/my_server/fart.mp3&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; (and its BZip2-compressed equivalent).&lt;br /&gt;
&lt;br /&gt;
You will need to also copy the files from the game server to the web server.&lt;br /&gt;
&lt;br /&gt;
== SourceMod extension not loading ==&lt;br /&gt;
&lt;br /&gt;
By default, if no plugin depends on an extension, it won't be loaded automatically, nor will it show up in &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;sm exts load ${extension}&amp;lt;/tt&amp;gt; if you'd like to test if it loads and to see if it fails, or add an &amp;lt;tt&amp;gt;${extension}.autoload&amp;lt;/tt&amp;gt; file (empty or not) in the extensions directory if you always want it to load.&lt;br /&gt;
&lt;br /&gt;
== RCON ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Source_RCON_Protocol Source RCON Protocol] allows users to remotely issue console commands to dedicated server instances.&lt;br /&gt;
&lt;br /&gt;
You likely won't need this, because you can issue console commands through&lt;br /&gt;
&lt;br /&gt;
* running the server instance in a terminal multiplexer session (with &amp;lt;tt&amp;gt;screen&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;tmux&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* your game server provider providing a web interface that provides real-time console input and output&lt;br /&gt;
&lt;br /&gt;
If you have full access to the machine that your server runs on, you can block RCON packets by dropping TCP packets going to the game port entirely.&lt;br /&gt;
&lt;br /&gt;
Note that doing so will also prevent use of third-party extensions that process TCP connections on the game port, such as [https://forums.alliedmods.net/showthread.php?t=270962 Conplex].&lt;br /&gt;
&lt;br /&gt;
You can use the following on Linux, if you are using iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# the following commands append rules to the firewall; the order here is important&lt;br /&gt;
# change 27015 to the game port&lt;br /&gt;
&lt;br /&gt;
# accept RCON traffic that comes from the same machine, for things like SourceBans&lt;br /&gt;
# if you know you aren't using anything else that relies on RCON you may omit this&lt;br /&gt;
# if legitimate RCON traffic may come from elsewhere, change the source network (-s 127.0.0.1/8),&lt;br /&gt;
# or append additional rules for addresses that should be allowed&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -s 127.0.0.1/8 -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
# drop everything else going to the game port&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Profiling ==&lt;br /&gt;
&lt;br /&gt;
In some cases you will run into server hitches.  If you have a general idea of when it happens, you can start the Source Engine's profiler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sm prof start vprof&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Continue playing, then once you think you've gathered enough data, you can stop profiling and have it dumped out to a file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sm prof stop&lt;br /&gt;
con_logfile &amp;quot;vproflog.txt&amp;quot;&lt;br /&gt;
sm prof dump vprof&lt;br /&gt;
con_logfile &amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The profiler results will be in &amp;lt;tt&amp;gt;vproflog.txt&amp;lt;/tt&amp;gt; in your game directory.&lt;br /&gt;
&lt;br /&gt;
= Platform-specific =&lt;br /&gt;
&lt;br /&gt;
== Linux extension failing to load on outdated &amp;lt;tt&amp;gt;GLIBCXX_*&amp;lt;/tt&amp;gt; version ==&lt;br /&gt;
&lt;br /&gt;
Various Source Engine games (Counter Strike: Source, Day of Defeat: Source, Counter Strike: Global Offensive, third-party games using the Source SDK modding system, possibly others) bundle standard libraries that are older than what current operating systems ship with, but newer than those that Valve ships as a baseline.&lt;br /&gt;
&lt;br /&gt;
Software that depends on new versions of libraries will fail to load.  This includes Metamod:Source, SourceMod, and other native code / plugins / extension.&lt;br /&gt;
&lt;br /&gt;
You can choose to do one of the following:&lt;br /&gt;
&lt;br /&gt;
* Remove any existing copies of &amp;lt;tt&amp;gt;bin/libstdc++.so.6&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to your game install directory (not the root of the filesytem); this will let the game load the system libraries.&lt;br /&gt;
** If you are on a 64-bit system, continue to the [[#64-bit_Linux_systems_and_32-bit_executables|next section]] to ensure the system's 32-bit libraries are actually available after removing the Valve-bundled copies.&lt;br /&gt;
* If your operating system is also dated, you will need rebuild the extension using an older build environment, or upgrade to a newer one.  If you plan on recompiling the extension, the [https://github.com/ValveSoftware/steam-runtime Steam Runtime SDK] is considered the baseline of support.&lt;br /&gt;
&lt;br /&gt;
== 64-bit Linux systems and 32-bit executables ==&lt;br /&gt;
&lt;br /&gt;
[https://sporks.space/2022/02/27/win32-is-the-stable-linux-userland-abi-and-the-consequences/ Unlike Windows], 64-bit Linux systems are not guaranteed to ship with full compatibility for 32-bit executables by default.&lt;br /&gt;
&lt;br /&gt;
Depending on your distribution, you will need to run one of the following commands as root to install the required packages / libraries:&lt;br /&gt;
&lt;br /&gt;
* Debian / Ubuntu: &amp;lt;tt&amp;gt;apt install gcc-multilib lib32z1&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Arch: &amp;lt;tt&amp;gt;pacman -S lib32-gcc-libs lib32-zlib&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Fedora: &amp;lt;tt&amp;gt;yum -y install glibc.i686 zlib.i686&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Game Specific =&lt;br /&gt;
&lt;br /&gt;
== Team Fortress 2 ==&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.teamfortress.com/wiki/Dedicated_server_configuration Dedicated server configuration] section on the Team Fortress 2 Official Wiki provides general configuration instructions.  Depending on the platform you're working on, you may also be interested in the sections for [https://wiki.teamfortress.com/wiki/Linux_dedicated_server Linux] and [https://wiki.teamfortress.com/wiki/Windows_dedicated_server Windows].&lt;br /&gt;
&lt;br /&gt;
=== Mann vs. Machine ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;tt&amp;gt;tf_mvm_min_players_to_start&amp;lt;/tt&amp;gt; to 1 to only require one player to ready up and start the mission.&lt;br /&gt;
&lt;br /&gt;
=== Steam Datagram Relay ===&lt;br /&gt;
&lt;br /&gt;
The Steam Datagram Relay routes both server and client connections through the Steam network, hiding the IP address of each from the other.&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;tt&amp;gt;-enablefakeip&amp;lt;/tt&amp;gt; in the server's launch options to enable.  The server will then report &amp;quot;FakeIP allocation succeeded&amp;quot; at the end of startup; use that IP address / port combination in your game client to connect to the server.  This allocation will change on every server startup.&lt;br /&gt;
&lt;br /&gt;
=== Using Workshop maps ===&lt;br /&gt;
&lt;br /&gt;
{{note|This section has instructions specific to Team Fortress 2, and will likely not carry over to other games such as Counter-Strike: Global Offensive.}}&lt;br /&gt;
&lt;br /&gt;
[https://www.teamfortress.com/post.php?id=17214 As described in the patch notes shortly after the feature was added], Valve's intent is for server operators to use map names in the form &amp;lt;tt&amp;gt;workshop/${mapid}&amp;lt;/tt&amp;gt;, where &amp;lt;tt&amp;gt;${mapid}&amp;lt;/tt&amp;gt; is the ID of the map in the Workshop.   For example, [https://steamcommunity.com/sharedfiles/filedetails/?id=619869471 Sulfur] has an ID of 619869471, so you would specify it as &amp;lt;tt&amp;gt;workshop/619869471&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This allows both the game server and any connected clients to retrieve the latest version of the map through Steam.&lt;br /&gt;
&lt;br /&gt;
You can use that form in any place that accepts maps, such as the &amp;lt;tt&amp;gt;map&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;changelevel&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nextlevel&amp;lt;/tt&amp;gt; commands (including &amp;lt;tt&amp;gt;+map&amp;lt;/tt&amp;gt; as a launch option), as well as the mapcycle file.  SourceMod itself has support to translate the names to their display forms and will do so in first-party plugins; third-party plugins and integrations (game server providers / panels and other software) may or may not support this functionality.&lt;br /&gt;
&lt;br /&gt;
'''Disregard any suggestions to subscribe to the map and copy the file to your game / fast download servers.'''  That is often repeated, yet bad advice, as:&lt;br /&gt;
&lt;br /&gt;
* Players will download the map from your download server instead of through Steam&lt;br /&gt;
* You will need to manually update the map whenever the Workshop version is updated&lt;br /&gt;
* Players may receive map mismatch errors and fail to connect if the non-Workshop release differs from the Workshop version&lt;br /&gt;
&lt;br /&gt;
Keep things simple and use the Valve-documented method.  If you insist on using a non-Workshop version, get it from the correct sources.&lt;br /&gt;
&lt;br /&gt;
=== Games that aren't ===&lt;br /&gt;
&lt;br /&gt;
Non-exhaustive list of Source Engine class-based shooters with a cartoon-like visual style based on the art of Dean Cornwell, J. C. Leyendecker, and Norman Rockwell, that aren't [https://store.steampowered.com/app/440/Team_Fortress_2/ Team Fortress 2]:&lt;br /&gt;
&lt;br /&gt;
* Team Fortress 2 Classic&lt;br /&gt;
* Open Fortress&lt;br /&gt;
&lt;br /&gt;
If you're developing plugins and asking questions about one of those games, please specifically name them.  These games are not guaranteed to behave the same as &amp;quot;retail&amp;quot; Team Fortress 2, and solutions that work for retail aren't guaranteed to work on third-party mods.&lt;br /&gt;
&lt;br /&gt;
== Counter-Strike: Global Offensive ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Dedicated_Servers#Advanced_Configuration Advanced Configuration] section on the Valve Developer Wiki describes server configuration unique to CS:GO. It's different from most other mods.&lt;br /&gt;
&lt;br /&gt;
=== Responsive server console when hibernating ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;sv_hibernate_ms&amp;lt;/code&amp;gt; to 0 to make the server console more responsive when no players are online.&lt;br /&gt;
&lt;br /&gt;
== Left 4 Dead 2 ==&lt;br /&gt;
&lt;br /&gt;
=== Disabling lobby system ===&lt;br /&gt;
&lt;br /&gt;
While developing plugins, you generally don't want players being connected through Steam's lobby system.  Add the following to &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_allow_lobby_connect_only &amp;quot;0&amp;quot;;&lt;br /&gt;
sv_password &amp;quot;password_to_connect_with&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Virtual Server Configuration =&lt;br /&gt;
&lt;br /&gt;
As a developer, you may need to test on multiple platforms. To avoid having another physical machine to work on, you can use virtualization to run an operating system on your desktop.&lt;br /&gt;
&lt;br /&gt;
== Virtualbox ==&lt;br /&gt;
&lt;br /&gt;
=== Networking ===&lt;br /&gt;
&lt;br /&gt;
==== Network Address Translation ====&lt;br /&gt;
&lt;br /&gt;
With NAT plus port forwarding, the minimum would be to forward UDP from one of the host's loopback IP addresses to the server port on the VM's address.  Forwarding TCP isn't necessary unless you are interested in using the RCON protocol.&lt;br /&gt;
&lt;br /&gt;
For example, given a virtual machine with an IP address of &amp;lt;tt&amp;gt;10.0.2.15&amp;lt;/tt&amp;gt; and the server listening on port 27015, you should configure NAT as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt; (host) &amp;amp;rarr; &amp;lt;tt&amp;gt;10.0.2.15:27015&amp;lt;/tt&amp;gt; (guest)&lt;br /&gt;
&lt;br /&gt;
You can then connect to the server from the host OS by connecting to &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Any loopback IP address on the host portion is acceptable to use (that is, any address starting with &amp;lt;tt&amp;gt;127.*.*.*&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Host-Only Adapter ====&lt;br /&gt;
&lt;br /&gt;
Enable the Host-Only Adapter on your VM and statically assign the address to be in the same network as your host operating system's adapter. This allows you to connect to the server without any additional networking complexities.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11450</id>
		<title>User:Nosoop/Guide/Game Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11450"/>
		<updated>2023-07-22T15:24:20Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Using Workshop maps */ Add note on +map&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine games often differ in configuration; here are some basic suggestions on how to set them up for either testing or production use.&lt;br /&gt;
&lt;br /&gt;
= General =&lt;br /&gt;
&lt;br /&gt;
The following section(s) apply to most, if not all games.&lt;br /&gt;
&lt;br /&gt;
== Fast Downloads ==&lt;br /&gt;
&lt;br /&gt;
The Source Engine normally provides downloads over the same channel as gameplay, which is rather slow.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;quot;Fast&amp;amp;quot; downloads are downloads served out-of-band over HTTP, and as such you will need to have a web (HTTP) server up and running to take advantage of this functionality.  This is highly recommended if you are running a server with any amount of custom content that a player needs to download (models, sounds, maps).&lt;br /&gt;
&lt;br /&gt;
If you're using a game server provider, you may already have access to a web server for fast download purposes; check with your provider to confirm.&lt;br /&gt;
&lt;br /&gt;
Examples of web servers include: [https://www.nginx.com/ nginx], [https://caddyserver.com/ Caddy], [https://httpd.apache.org/ Apache], [https://www.rejetto.com/hfs/ HFS], and [https://en.wikipedia.org/wiki/Comparison_of_web_server_software many others] (and many more not included in that list).&lt;br /&gt;
&lt;br /&gt;
Once you have an HTTP server running, configure &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_downloadurl &amp;amp;quot;http://{your_server_location}/{path}&amp;amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The URL must be quoted, as &amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; is treated as the start of a comment and if left unquoted, the rest of the line will be ignored.  Do not include a trailing slash &amp;amp;mdash; the game client adds one when making the request; web servers are not guaranteed to collapse double slashes in the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;{path}&amp;lt;/tt&amp;gt; should be the path on your server that would translate to the root of your game server.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a file &amp;lt;tt&amp;gt;sound/my_server/fart.mp3&amp;lt;/tt&amp;gt; and an &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;, the client will request &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads/sound/my_server/fart.mp3&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; (and its BZip2-compressed equivalent).&lt;br /&gt;
&lt;br /&gt;
You will need to also copy the files from the game server to the web server.&lt;br /&gt;
&lt;br /&gt;
== SourceMod extension not loading ==&lt;br /&gt;
&lt;br /&gt;
By default, if no plugin depends on an extension, it won't be loaded automatically, nor will it show up in &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;sm exts load ${extension}&amp;lt;/tt&amp;gt; if you'd like to test if it loads and to see if it fails, or add an &amp;lt;tt&amp;gt;${extension}.autoload&amp;lt;/tt&amp;gt; file (empty or not) in the extensions directory if you always want it to load.&lt;br /&gt;
&lt;br /&gt;
== RCON ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Source_RCON_Protocol Source RCON Protocol] allows users to remotely issue console commands to dedicated server instances.&lt;br /&gt;
&lt;br /&gt;
You likely won't need this, because you can issue console commands through&lt;br /&gt;
&lt;br /&gt;
* running the server instance in a terminal multiplexer session (with &amp;lt;tt&amp;gt;screen&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;tmux&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* your game server provider providing a web interface that provides real-time console input and output&lt;br /&gt;
&lt;br /&gt;
If you have full access to the machine that your server runs on, you can block RCON packets by dropping TCP packets going to the game port entirely.&lt;br /&gt;
&lt;br /&gt;
Note that doing so will also prevent use of third-party extensions that process TCP connections on the game port, such as [https://forums.alliedmods.net/showthread.php?t=270962 Conplex].&lt;br /&gt;
&lt;br /&gt;
You can use the following on Linux, if you are using iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# the following commands append rules to the firewall; the order here is important&lt;br /&gt;
# change 27015 to the game port&lt;br /&gt;
&lt;br /&gt;
# accept RCON traffic that comes from the same machine, for things like SourceBans&lt;br /&gt;
# if you know you aren't using anything else that relies on RCON you may omit this&lt;br /&gt;
# if legitimate RCON traffic may come from elsewhere, change the source network (-s 127.0.0.1/8),&lt;br /&gt;
# or append additional rules for addresses that should be allowed&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -s 127.0.0.1/8 -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
# drop everything else going to the game port&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Platform-specific =&lt;br /&gt;
&lt;br /&gt;
== Linux extension failing to load on outdated &amp;lt;tt&amp;gt;GLIBCXX_*&amp;lt;/tt&amp;gt; version ==&lt;br /&gt;
&lt;br /&gt;
Various Source Engine games (Counter Strike: Source, Day of Defeat: Source, Counter Strike: Global Offensive, third-party games using the Source SDK modding system, possibly others) bundle standard libraries that are older than what current operating systems ship with, but newer than those that Valve ships as a baseline.&lt;br /&gt;
&lt;br /&gt;
Software that depends on new versions of libraries will fail to load.  This includes Metamod:Source, SourceMod, and other native code / plugins / extension.&lt;br /&gt;
&lt;br /&gt;
You can choose to do one of the following:&lt;br /&gt;
&lt;br /&gt;
* Remove any existing copies of &amp;lt;tt&amp;gt;bin/libstdc++.so.6&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to your game install directory (not the root of the filesytem); this will let the game load the system libraries.&lt;br /&gt;
** If you are on a 64-bit system, continue to the [[#64-bit_Linux_systems_and_32-bit_executables|next section]] to ensure the system's 32-bit libraries are actually available after removing the Valve-bundled copies.&lt;br /&gt;
* If your operating system is also dated, you will need rebuild the extension using an older build environment, or upgrade to a newer one.  If you plan on recompiling the extension, the [https://github.com/ValveSoftware/steam-runtime Steam Runtime SDK] is considered the baseline of support.&lt;br /&gt;
&lt;br /&gt;
== 64-bit Linux systems and 32-bit executables ==&lt;br /&gt;
&lt;br /&gt;
[https://sporks.space/2022/02/27/win32-is-the-stable-linux-userland-abi-and-the-consequences/ Unlike Windows], 64-bit Linux systems are not guaranteed to ship with full compatibility for 32-bit executables by default.&lt;br /&gt;
&lt;br /&gt;
Depending on your distribution, you will need to run one of the following commands as root to install the required packages / libraries:&lt;br /&gt;
&lt;br /&gt;
* Debian / Ubuntu: &amp;lt;tt&amp;gt;apt install gcc-multilib lib32z1&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Arch: &amp;lt;tt&amp;gt;pacman -S lib32-gcc-libs lib32-zlib&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Fedora: &amp;lt;tt&amp;gt;yum -y install glibc.i686 zlib.i686&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Game Specific =&lt;br /&gt;
&lt;br /&gt;
== Team Fortress 2 ==&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.teamfortress.com/wiki/Dedicated_server_configuration Dedicated server configuration] section on the Team Fortress 2 Official Wiki provides general configuration instructions.  Depending on the platform you're working on, you may also be interested in the sections for [https://wiki.teamfortress.com/wiki/Linux_dedicated_server Linux] and [https://wiki.teamfortress.com/wiki/Windows_dedicated_server Windows].&lt;br /&gt;
&lt;br /&gt;
=== Mann vs. Machine ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;tt&amp;gt;tf_mvm_min_players_to_start&amp;lt;/tt&amp;gt; to 1 to only require one player to ready up and start the mission.&lt;br /&gt;
&lt;br /&gt;
=== Steam Datagram Relay ===&lt;br /&gt;
&lt;br /&gt;
The Steam Datagram Relay routes both server and client connections through the Steam network, hiding the IP address of each from the other.&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;tt&amp;gt;-enablefakeip&amp;lt;/tt&amp;gt; in the server's launch options to enable.  The server will then report &amp;quot;FakeIP allocation succeeded&amp;quot; at the end of startup; use that IP address / port combination in your game client to connect to the server.  This allocation will change on every server startup.&lt;br /&gt;
&lt;br /&gt;
=== Using Workshop maps ===&lt;br /&gt;
&lt;br /&gt;
{{note|This section has instructions specific to Team Fortress 2, and will likely not carry over to other games such as Counter-Strike: Global Offensive.}}&lt;br /&gt;
&lt;br /&gt;
[https://www.teamfortress.com/post.php?id=17214 As described in the patch notes shortly after the feature was added], Valve's intent is for server operators to use map names in the form &amp;lt;tt&amp;gt;workshop/${mapid}&amp;lt;/tt&amp;gt;, where &amp;lt;tt&amp;gt;${mapid}&amp;lt;/tt&amp;gt; is the ID of the map in the Workshop.   For example, [https://steamcommunity.com/sharedfiles/filedetails/?id=619869471 Sulfur] has an ID of 619869471, so you would specify it as &amp;lt;tt&amp;gt;workshop/619869471&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This allows both the game server and any connected clients to retrieve the latest version of the map through Steam.&lt;br /&gt;
&lt;br /&gt;
You can use that form in any place that accepts maps, such as the &amp;lt;tt&amp;gt;map&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;changelevel&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nextlevel&amp;lt;/tt&amp;gt; commands (including &amp;lt;tt&amp;gt;+map&amp;lt;/tt&amp;gt; as a launch option), as well as the mapcycle file.  SourceMod itself has support to translate the names to their display forms and will do so in first-party plugins; third-party plugins and integrations (game server providers / panels and other software) may or may not support this functionality.&lt;br /&gt;
&lt;br /&gt;
'''Disregard any suggestions to subscribe to the map and copy the file to your game / fast download servers.'''  That is often repeated, yet bad advice, as:&lt;br /&gt;
&lt;br /&gt;
* Players will download the map from your download server instead of through Steam&lt;br /&gt;
* You will need to manually update the map whenever the Workshop version is updated&lt;br /&gt;
* Players may receive map mismatch errors and fail to connect if the non-Workshop release differs from the Workshop version&lt;br /&gt;
&lt;br /&gt;
Keep things simple and use the Valve-documented method.  If you insist on using a non-Workshop version, get it from the correct sources.&lt;br /&gt;
&lt;br /&gt;
=== Games that aren't ===&lt;br /&gt;
&lt;br /&gt;
Non-exhaustive list of Source Engine class-based shooters with a cartoon-like visual style based on the art of Dean Cornwell, J. C. Leyendecker, and Norman Rockwell, that aren't [https://store.steampowered.com/app/440/Team_Fortress_2/ Team Fortress 2]:&lt;br /&gt;
&lt;br /&gt;
* Team Fortress 2 Classic&lt;br /&gt;
* Open Fortress&lt;br /&gt;
&lt;br /&gt;
If you're developing plugins and asking questions about one of those games, please specifically name them.  These games are not guaranteed to behave the same as &amp;quot;retail&amp;quot; Team Fortress 2, and solutions that work for retail aren't guaranteed to work on third-party mods.&lt;br /&gt;
&lt;br /&gt;
== Counter-Strike: Global Offensive ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Dedicated_Servers#Advanced_Configuration Advanced Configuration] section on the Valve Developer Wiki describes server configuration unique to CS:GO. It's different from most other mods.&lt;br /&gt;
&lt;br /&gt;
=== Responsive server console when hibernating ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;sv_hibernate_ms&amp;lt;/code&amp;gt; to 0 to make the server console more responsive when no players are online.&lt;br /&gt;
&lt;br /&gt;
== Left 4 Dead 2 ==&lt;br /&gt;
&lt;br /&gt;
=== Disabling lobby system ===&lt;br /&gt;
&lt;br /&gt;
While developing plugins, you generally don't want players being connected through Steam's lobby system.  Add the following to &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_allow_lobby_connect_only &amp;quot;0&amp;quot;;&lt;br /&gt;
sv_password &amp;quot;password_to_connect_with&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Virtual Server Configuration =&lt;br /&gt;
&lt;br /&gt;
As a developer, you may need to test on multiple platforms. To avoid having another physical machine to work on, you can use virtualization to run an operating system on your desktop.&lt;br /&gt;
&lt;br /&gt;
== Virtualbox ==&lt;br /&gt;
&lt;br /&gt;
=== Networking ===&lt;br /&gt;
&lt;br /&gt;
==== Network Address Translation ====&lt;br /&gt;
&lt;br /&gt;
With NAT plus port forwarding, the minimum would be to forward UDP from one of the host's loopback IP addresses to the server port on the VM's address.  Forwarding TCP isn't necessary unless you are interested in using the RCON protocol.&lt;br /&gt;
&lt;br /&gt;
For example, given a virtual machine with an IP address of &amp;lt;tt&amp;gt;10.0.2.15&amp;lt;/tt&amp;gt; and the server listening on port 27015, you should configure NAT as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt; (host) &amp;amp;rarr; &amp;lt;tt&amp;gt;10.0.2.15:27015&amp;lt;/tt&amp;gt; (guest)&lt;br /&gt;
&lt;br /&gt;
You can then connect to the server from the host OS by connecting to &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Any loopback IP address on the host portion is acceptable to use (that is, any address starting with &amp;lt;tt&amp;gt;127.*.*.*&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Host-Only Adapter ====&lt;br /&gt;
&lt;br /&gt;
Enable the Host-Only Adapter on your VM and statically assign the address to be in the same network as your host operating system's adapter. This allows you to connect to the server without any additional networking complexities.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11449</id>
		<title>User:Nosoop/Guide/Game Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11449"/>
		<updated>2023-07-22T15:22:58Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Using Workshop maps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine games often differ in configuration; here are some basic suggestions on how to set them up for either testing or production use.&lt;br /&gt;
&lt;br /&gt;
= General =&lt;br /&gt;
&lt;br /&gt;
The following section(s) apply to most, if not all games.&lt;br /&gt;
&lt;br /&gt;
== Fast Downloads ==&lt;br /&gt;
&lt;br /&gt;
The Source Engine normally provides downloads over the same channel as gameplay, which is rather slow.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;quot;Fast&amp;amp;quot; downloads are downloads served out-of-band over HTTP, and as such you will need to have a web (HTTP) server up and running to take advantage of this functionality.  This is highly recommended if you are running a server with any amount of custom content that a player needs to download (models, sounds, maps).&lt;br /&gt;
&lt;br /&gt;
If you're using a game server provider, you may already have access to a web server for fast download purposes; check with your provider to confirm.&lt;br /&gt;
&lt;br /&gt;
Examples of web servers include: [https://www.nginx.com/ nginx], [https://caddyserver.com/ Caddy], [https://httpd.apache.org/ Apache], [https://www.rejetto.com/hfs/ HFS], and [https://en.wikipedia.org/wiki/Comparison_of_web_server_software many others] (and many more not included in that list).&lt;br /&gt;
&lt;br /&gt;
Once you have an HTTP server running, configure &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_downloadurl &amp;amp;quot;http://{your_server_location}/{path}&amp;amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The URL must be quoted, as &amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; is treated as the start of a comment and if left unquoted, the rest of the line will be ignored.  Do not include a trailing slash &amp;amp;mdash; the game client adds one when making the request; web servers are not guaranteed to collapse double slashes in the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;{path}&amp;lt;/tt&amp;gt; should be the path on your server that would translate to the root of your game server.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a file &amp;lt;tt&amp;gt;sound/my_server/fart.mp3&amp;lt;/tt&amp;gt; and an &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;, the client will request &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads/sound/my_server/fart.mp3&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; (and its BZip2-compressed equivalent).&lt;br /&gt;
&lt;br /&gt;
You will need to also copy the files from the game server to the web server.&lt;br /&gt;
&lt;br /&gt;
== SourceMod extension not loading ==&lt;br /&gt;
&lt;br /&gt;
By default, if no plugin depends on an extension, it won't be loaded automatically, nor will it show up in &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;sm exts load ${extension}&amp;lt;/tt&amp;gt; if you'd like to test if it loads and to see if it fails, or add an &amp;lt;tt&amp;gt;${extension}.autoload&amp;lt;/tt&amp;gt; file (empty or not) in the extensions directory if you always want it to load.&lt;br /&gt;
&lt;br /&gt;
== RCON ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Source_RCON_Protocol Source RCON Protocol] allows users to remotely issue console commands to dedicated server instances.&lt;br /&gt;
&lt;br /&gt;
You likely won't need this, because you can issue console commands through&lt;br /&gt;
&lt;br /&gt;
* running the server instance in a terminal multiplexer session (with &amp;lt;tt&amp;gt;screen&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;tmux&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* your game server provider providing a web interface that provides real-time console input and output&lt;br /&gt;
&lt;br /&gt;
If you have full access to the machine that your server runs on, you can block RCON packets by dropping TCP packets going to the game port entirely.&lt;br /&gt;
&lt;br /&gt;
Note that doing so will also prevent use of third-party extensions that process TCP connections on the game port, such as [https://forums.alliedmods.net/showthread.php?t=270962 Conplex].&lt;br /&gt;
&lt;br /&gt;
You can use the following on Linux, if you are using iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# the following commands append rules to the firewall; the order here is important&lt;br /&gt;
# change 27015 to the game port&lt;br /&gt;
&lt;br /&gt;
# accept RCON traffic that comes from the same machine, for things like SourceBans&lt;br /&gt;
# if you know you aren't using anything else that relies on RCON you may omit this&lt;br /&gt;
# if legitimate RCON traffic may come from elsewhere, change the source network (-s 127.0.0.1/8),&lt;br /&gt;
# or append additional rules for addresses that should be allowed&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -s 127.0.0.1/8 -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
# drop everything else going to the game port&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Platform-specific =&lt;br /&gt;
&lt;br /&gt;
== Linux extension failing to load on outdated &amp;lt;tt&amp;gt;GLIBCXX_*&amp;lt;/tt&amp;gt; version ==&lt;br /&gt;
&lt;br /&gt;
Various Source Engine games (Counter Strike: Source, Day of Defeat: Source, Counter Strike: Global Offensive, third-party games using the Source SDK modding system, possibly others) bundle standard libraries that are older than what current operating systems ship with, but newer than those that Valve ships as a baseline.&lt;br /&gt;
&lt;br /&gt;
Software that depends on new versions of libraries will fail to load.  This includes Metamod:Source, SourceMod, and other native code / plugins / extension.&lt;br /&gt;
&lt;br /&gt;
You can choose to do one of the following:&lt;br /&gt;
&lt;br /&gt;
* Remove any existing copies of &amp;lt;tt&amp;gt;bin/libstdc++.so.6&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to your game install directory (not the root of the filesytem); this will let the game load the system libraries.&lt;br /&gt;
** If you are on a 64-bit system, continue to the [[#64-bit_Linux_systems_and_32-bit_executables|next section]] to ensure the system's 32-bit libraries are actually available after removing the Valve-bundled copies.&lt;br /&gt;
* If your operating system is also dated, you will need rebuild the extension using an older build environment, or upgrade to a newer one.  If you plan on recompiling the extension, the [https://github.com/ValveSoftware/steam-runtime Steam Runtime SDK] is considered the baseline of support.&lt;br /&gt;
&lt;br /&gt;
== 64-bit Linux systems and 32-bit executables ==&lt;br /&gt;
&lt;br /&gt;
[https://sporks.space/2022/02/27/win32-is-the-stable-linux-userland-abi-and-the-consequences/ Unlike Windows], 64-bit Linux systems are not guaranteed to ship with full compatibility for 32-bit executables by default.&lt;br /&gt;
&lt;br /&gt;
Depending on your distribution, you will need to run one of the following commands as root to install the required packages / libraries:&lt;br /&gt;
&lt;br /&gt;
* Debian / Ubuntu: &amp;lt;tt&amp;gt;apt install gcc-multilib lib32z1&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Arch: &amp;lt;tt&amp;gt;pacman -S lib32-gcc-libs lib32-zlib&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Fedora: &amp;lt;tt&amp;gt;yum -y install glibc.i686 zlib.i686&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Game Specific =&lt;br /&gt;
&lt;br /&gt;
== Team Fortress 2 ==&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.teamfortress.com/wiki/Dedicated_server_configuration Dedicated server configuration] section on the Team Fortress 2 Official Wiki provides general configuration instructions.  Depending on the platform you're working on, you may also be interested in the sections for [https://wiki.teamfortress.com/wiki/Linux_dedicated_server Linux] and [https://wiki.teamfortress.com/wiki/Windows_dedicated_server Windows].&lt;br /&gt;
&lt;br /&gt;
=== Mann vs. Machine ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;tt&amp;gt;tf_mvm_min_players_to_start&amp;lt;/tt&amp;gt; to 1 to only require one player to ready up and start the mission.&lt;br /&gt;
&lt;br /&gt;
=== Steam Datagram Relay ===&lt;br /&gt;
&lt;br /&gt;
The Steam Datagram Relay routes both server and client connections through the Steam network, hiding the IP address of each from the other.&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;tt&amp;gt;-enablefakeip&amp;lt;/tt&amp;gt; in the server's launch options to enable.  The server will then report &amp;quot;FakeIP allocation succeeded&amp;quot; at the end of startup; use that IP address / port combination in your game client to connect to the server.  This allocation will change on every server startup.&lt;br /&gt;
&lt;br /&gt;
=== Using Workshop maps ===&lt;br /&gt;
&lt;br /&gt;
{{note|This section has instructions specific to Team Fortress 2, and will likely not carry over to other games such as Counter-Strike: Global Offensive.}}&lt;br /&gt;
&lt;br /&gt;
[https://www.teamfortress.com/post.php?id=17214 As described in the patch notes shortly after the feature was added], Valve's intent is for server operators to use map names in the form &amp;lt;tt&amp;gt;workshop/${mapid}&amp;lt;/tt&amp;gt;, where &amp;lt;tt&amp;gt;${mapid}&amp;lt;/tt&amp;gt; is the ID of the map in the Workshop.   For example, [https://steamcommunity.com/sharedfiles/filedetails/?id=619869471 Sulfur] has an ID of 619869471, so you would specify it as &amp;lt;tt&amp;gt;workshop/619869471&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This allows both the game server and any connected clients to retrieve the latest version of the map through Steam.&lt;br /&gt;
&lt;br /&gt;
You can use that form in any place that accepts maps, such as the &amp;lt;tt&amp;gt;map&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;changelevel&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nextlevel&amp;lt;/tt&amp;gt; commands, as well as the mapcycle file.  SourceMod itself has support to translate the names to their display forms and will do so in first-party plugins; third-party plugins and integrations (game server providers / panels and other software) may or may not support this functionality.&lt;br /&gt;
&lt;br /&gt;
'''Disregard any suggestions to subscribe to the map and copy the file to your game / fast download servers.'''  That is often repeated, yet bad advice, as:&lt;br /&gt;
&lt;br /&gt;
* Players will download the map from your download server instead of through Steam&lt;br /&gt;
* You will need to manually update the map whenever the Workshop version is updated&lt;br /&gt;
* Players may receive map mismatch errors and fail to connect if the non-Workshop release differs from the Workshop version&lt;br /&gt;
&lt;br /&gt;
Keep things simple and use the Valve-documented method.  If you insist on using a non-Workshop version, get it from the correct sources.&lt;br /&gt;
&lt;br /&gt;
=== Games that aren't ===&lt;br /&gt;
&lt;br /&gt;
Non-exhaustive list of Source Engine class-based shooters with a cartoon-like visual style based on the art of Dean Cornwell, J. C. Leyendecker, and Norman Rockwell, that aren't [https://store.steampowered.com/app/440/Team_Fortress_2/ Team Fortress 2]:&lt;br /&gt;
&lt;br /&gt;
* Team Fortress 2 Classic&lt;br /&gt;
* Open Fortress&lt;br /&gt;
&lt;br /&gt;
If you're developing plugins and asking questions about one of those games, please specifically name them.  These games are not guaranteed to behave the same as &amp;quot;retail&amp;quot; Team Fortress 2, and solutions that work for retail aren't guaranteed to work on third-party mods.&lt;br /&gt;
&lt;br /&gt;
== Counter-Strike: Global Offensive ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Dedicated_Servers#Advanced_Configuration Advanced Configuration] section on the Valve Developer Wiki describes server configuration unique to CS:GO. It's different from most other mods.&lt;br /&gt;
&lt;br /&gt;
=== Responsive server console when hibernating ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;sv_hibernate_ms&amp;lt;/code&amp;gt; to 0 to make the server console more responsive when no players are online.&lt;br /&gt;
&lt;br /&gt;
== Left 4 Dead 2 ==&lt;br /&gt;
&lt;br /&gt;
=== Disabling lobby system ===&lt;br /&gt;
&lt;br /&gt;
While developing plugins, you generally don't want players being connected through Steam's lobby system.  Add the following to &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_allow_lobby_connect_only &amp;quot;0&amp;quot;;&lt;br /&gt;
sv_password &amp;quot;password_to_connect_with&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Virtual Server Configuration =&lt;br /&gt;
&lt;br /&gt;
As a developer, you may need to test on multiple platforms. To avoid having another physical machine to work on, you can use virtualization to run an operating system on your desktop.&lt;br /&gt;
&lt;br /&gt;
== Virtualbox ==&lt;br /&gt;
&lt;br /&gt;
=== Networking ===&lt;br /&gt;
&lt;br /&gt;
==== Network Address Translation ====&lt;br /&gt;
&lt;br /&gt;
With NAT plus port forwarding, the minimum would be to forward UDP from one of the host's loopback IP addresses to the server port on the VM's address.  Forwarding TCP isn't necessary unless you are interested in using the RCON protocol.&lt;br /&gt;
&lt;br /&gt;
For example, given a virtual machine with an IP address of &amp;lt;tt&amp;gt;10.0.2.15&amp;lt;/tt&amp;gt; and the server listening on port 27015, you should configure NAT as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt; (host) &amp;amp;rarr; &amp;lt;tt&amp;gt;10.0.2.15:27015&amp;lt;/tt&amp;gt; (guest)&lt;br /&gt;
&lt;br /&gt;
You can then connect to the server from the host OS by connecting to &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Any loopback IP address on the host portion is acceptable to use (that is, any address starting with &amp;lt;tt&amp;gt;127.*.*.*&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Host-Only Adapter ====&lt;br /&gt;
&lt;br /&gt;
Enable the Host-Only Adapter on your VM and statically assign the address to be in the same network as your host operating system's adapter. This allows you to connect to the server without any additional networking complexities.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11448</id>
		<title>User:Nosoop/Guide/Game Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11448"/>
		<updated>2023-07-22T15:15:26Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Using Workshop maps */ Next person to suggest subscribing dies&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine games often differ in configuration; here are some basic suggestions on how to set them up for either testing or production use.&lt;br /&gt;
&lt;br /&gt;
= General =&lt;br /&gt;
&lt;br /&gt;
The following section(s) apply to most, if not all games.&lt;br /&gt;
&lt;br /&gt;
== Fast Downloads ==&lt;br /&gt;
&lt;br /&gt;
The Source Engine normally provides downloads over the same channel as gameplay, which is rather slow.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;quot;Fast&amp;amp;quot; downloads are downloads served out-of-band over HTTP, and as such you will need to have a web (HTTP) server up and running to take advantage of this functionality.  This is highly recommended if you are running a server with any amount of custom content that a player needs to download (models, sounds, maps).&lt;br /&gt;
&lt;br /&gt;
If you're using a game server provider, you may already have access to a web server for fast download purposes; check with your provider to confirm.&lt;br /&gt;
&lt;br /&gt;
Examples of web servers include: [https://www.nginx.com/ nginx], [https://caddyserver.com/ Caddy], [https://httpd.apache.org/ Apache], [https://www.rejetto.com/hfs/ HFS], and [https://en.wikipedia.org/wiki/Comparison_of_web_server_software many others] (and many more not included in that list).&lt;br /&gt;
&lt;br /&gt;
Once you have an HTTP server running, configure &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_downloadurl &amp;amp;quot;http://{your_server_location}/{path}&amp;amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The URL must be quoted, as &amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; is treated as the start of a comment and if left unquoted, the rest of the line will be ignored.  Do not include a trailing slash &amp;amp;mdash; the game client adds one when making the request; web servers are not guaranteed to collapse double slashes in the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;{path}&amp;lt;/tt&amp;gt; should be the path on your server that would translate to the root of your game server.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a file &amp;lt;tt&amp;gt;sound/my_server/fart.mp3&amp;lt;/tt&amp;gt; and an &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;, the client will request &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads/sound/my_server/fart.mp3&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; (and its BZip2-compressed equivalent).&lt;br /&gt;
&lt;br /&gt;
You will need to also copy the files from the game server to the web server.&lt;br /&gt;
&lt;br /&gt;
== SourceMod extension not loading ==&lt;br /&gt;
&lt;br /&gt;
By default, if no plugin depends on an extension, it won't be loaded automatically, nor will it show up in &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;sm exts load ${extension}&amp;lt;/tt&amp;gt; if you'd like to test if it loads and to see if it fails, or add an &amp;lt;tt&amp;gt;${extension}.autoload&amp;lt;/tt&amp;gt; file (empty or not) in the extensions directory if you always want it to load.&lt;br /&gt;
&lt;br /&gt;
== RCON ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Source_RCON_Protocol Source RCON Protocol] allows users to remotely issue console commands to dedicated server instances.&lt;br /&gt;
&lt;br /&gt;
You likely won't need this, because you can issue console commands through&lt;br /&gt;
&lt;br /&gt;
* running the server instance in a terminal multiplexer session (with &amp;lt;tt&amp;gt;screen&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;tmux&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* your game server provider providing a web interface that provides real-time console input and output&lt;br /&gt;
&lt;br /&gt;
If you have full access to the machine that your server runs on, you can block RCON packets by dropping TCP packets going to the game port entirely.&lt;br /&gt;
&lt;br /&gt;
Note that doing so will also prevent use of third-party extensions that process TCP connections on the game port, such as [https://forums.alliedmods.net/showthread.php?t=270962 Conplex].&lt;br /&gt;
&lt;br /&gt;
You can use the following on Linux, if you are using iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# the following commands append rules to the firewall; the order here is important&lt;br /&gt;
# change 27015 to the game port&lt;br /&gt;
&lt;br /&gt;
# accept RCON traffic that comes from the same machine, for things like SourceBans&lt;br /&gt;
# if you know you aren't using anything else that relies on RCON you may omit this&lt;br /&gt;
# if legitimate RCON traffic may come from elsewhere, change the source network (-s 127.0.0.1/8),&lt;br /&gt;
# or append additional rules for addresses that should be allowed&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -s 127.0.0.1/8 -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
# drop everything else going to the game port&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Platform-specific =&lt;br /&gt;
&lt;br /&gt;
== Linux extension failing to load on outdated &amp;lt;tt&amp;gt;GLIBCXX_*&amp;lt;/tt&amp;gt; version ==&lt;br /&gt;
&lt;br /&gt;
Various Source Engine games (Counter Strike: Source, Day of Defeat: Source, Counter Strike: Global Offensive, third-party games using the Source SDK modding system, possibly others) bundle standard libraries that are older than what current operating systems ship with, but newer than those that Valve ships as a baseline.&lt;br /&gt;
&lt;br /&gt;
Software that depends on new versions of libraries will fail to load.  This includes Metamod:Source, SourceMod, and other native code / plugins / extension.&lt;br /&gt;
&lt;br /&gt;
You can choose to do one of the following:&lt;br /&gt;
&lt;br /&gt;
* Remove any existing copies of &amp;lt;tt&amp;gt;bin/libstdc++.so.6&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to your game install directory (not the root of the filesytem); this will let the game load the system libraries.&lt;br /&gt;
** If you are on a 64-bit system, continue to the [[#64-bit_Linux_systems_and_32-bit_executables|next section]] to ensure the system's 32-bit libraries are actually available after removing the Valve-bundled copies.&lt;br /&gt;
* If your operating system is also dated, you will need rebuild the extension using an older build environment, or upgrade to a newer one.  If you plan on recompiling the extension, the [https://github.com/ValveSoftware/steam-runtime Steam Runtime SDK] is considered the baseline of support.&lt;br /&gt;
&lt;br /&gt;
== 64-bit Linux systems and 32-bit executables ==&lt;br /&gt;
&lt;br /&gt;
[https://sporks.space/2022/02/27/win32-is-the-stable-linux-userland-abi-and-the-consequences/ Unlike Windows], 64-bit Linux systems are not guaranteed to ship with full compatibility for 32-bit executables by default.&lt;br /&gt;
&lt;br /&gt;
Depending on your distribution, you will need to run one of the following commands as root to install the required packages / libraries:&lt;br /&gt;
&lt;br /&gt;
* Debian / Ubuntu: &amp;lt;tt&amp;gt;apt install gcc-multilib lib32z1&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Arch: &amp;lt;tt&amp;gt;pacman -S lib32-gcc-libs lib32-zlib&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Fedora: &amp;lt;tt&amp;gt;yum -y install glibc.i686 zlib.i686&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Game Specific =&lt;br /&gt;
&lt;br /&gt;
== Team Fortress 2 ==&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.teamfortress.com/wiki/Dedicated_server_configuration Dedicated server configuration] section on the Team Fortress 2 Official Wiki provides general configuration instructions.  Depending on the platform you're working on, you may also be interested in the sections for [https://wiki.teamfortress.com/wiki/Linux_dedicated_server Linux] and [https://wiki.teamfortress.com/wiki/Windows_dedicated_server Windows].&lt;br /&gt;
&lt;br /&gt;
=== Mann vs. Machine ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;tt&amp;gt;tf_mvm_min_players_to_start&amp;lt;/tt&amp;gt; to 1 to only require one player to ready up and start the mission.&lt;br /&gt;
&lt;br /&gt;
=== Steam Datagram Relay ===&lt;br /&gt;
&lt;br /&gt;
The Steam Datagram Relay routes both server and client connections through the Steam network, hiding the IP address of each from the other.&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;tt&amp;gt;-enablefakeip&amp;lt;/tt&amp;gt; in the server's launch options to enable.  The server will then report &amp;quot;FakeIP allocation succeeded&amp;quot; at the end of startup; use that IP address / port combination in your game client to connect to the server.  This allocation will change on every server startup.&lt;br /&gt;
&lt;br /&gt;
=== Using Workshop maps ===&lt;br /&gt;
&lt;br /&gt;
{{note|This section has instructions specific to Team Fortress 2, and will likely not carry over to other games such as Counter-Strike: Global Offensive.}}&lt;br /&gt;
&lt;br /&gt;
[https://www.teamfortress.com/post.php?id=17214 As described in the patch notes shortly after the feature was added], Valve's intent is for server operators to use map names in the form &amp;lt;tt&amp;gt;workshop/${mapid}&amp;lt;/tt&amp;gt;, where &amp;lt;tt&amp;gt;${mapid}&amp;lt;/tt&amp;gt; is the ID of the map in the Workshop.   For example, [https://steamcommunity.com/sharedfiles/filedetails/?id=619869471 Sulfur] has an ID of 619869471, so you would specify it as &amp;lt;tt&amp;gt;workshop/619869471&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This allows both the game server and any connected clients to retrieve the map through Steam.&lt;br /&gt;
&lt;br /&gt;
You can use that form in any place that accepts maps, such as the &amp;lt;tt&amp;gt;map&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;changelevel&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nextlevel&amp;lt;/tt&amp;gt; commands as well as the mapcycle file.  SourceMod itself has support to translate the names to their display forms and will do so in first-party plugins; third-party plugins may or may not support this functionality.&lt;br /&gt;
&lt;br /&gt;
'''Disregard any suggestions to subscribe to the map and copy the file to your game / fast download servers.'''  That is often repeated, yet bad advice.&lt;br /&gt;
&lt;br /&gt;
=== Games that aren't ===&lt;br /&gt;
&lt;br /&gt;
Non-exhaustive list of Source Engine class-based shooters with a cartoon-like visual style based on the art of Dean Cornwell, J. C. Leyendecker, and Norman Rockwell, that aren't [https://store.steampowered.com/app/440/Team_Fortress_2/ Team Fortress 2]:&lt;br /&gt;
&lt;br /&gt;
* Team Fortress 2 Classic&lt;br /&gt;
* Open Fortress&lt;br /&gt;
&lt;br /&gt;
If you're developing plugins and asking questions about one of those games, please specifically name them.  These games are not guaranteed to behave the same as &amp;quot;retail&amp;quot; Team Fortress 2, and solutions that work for retail aren't guaranteed to work on third-party mods.&lt;br /&gt;
&lt;br /&gt;
== Counter-Strike: Global Offensive ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Dedicated_Servers#Advanced_Configuration Advanced Configuration] section on the Valve Developer Wiki describes server configuration unique to CS:GO. It's different from most other mods.&lt;br /&gt;
&lt;br /&gt;
=== Responsive server console when hibernating ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;sv_hibernate_ms&amp;lt;/code&amp;gt; to 0 to make the server console more responsive when no players are online.&lt;br /&gt;
&lt;br /&gt;
== Left 4 Dead 2 ==&lt;br /&gt;
&lt;br /&gt;
=== Disabling lobby system ===&lt;br /&gt;
&lt;br /&gt;
While developing plugins, you generally don't want players being connected through Steam's lobby system.  Add the following to &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_allow_lobby_connect_only &amp;quot;0&amp;quot;;&lt;br /&gt;
sv_password &amp;quot;password_to_connect_with&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Virtual Server Configuration =&lt;br /&gt;
&lt;br /&gt;
As a developer, you may need to test on multiple platforms. To avoid having another physical machine to work on, you can use virtualization to run an operating system on your desktop.&lt;br /&gt;
&lt;br /&gt;
== Virtualbox ==&lt;br /&gt;
&lt;br /&gt;
=== Networking ===&lt;br /&gt;
&lt;br /&gt;
==== Network Address Translation ====&lt;br /&gt;
&lt;br /&gt;
With NAT plus port forwarding, the minimum would be to forward UDP from one of the host's loopback IP addresses to the server port on the VM's address.  Forwarding TCP isn't necessary unless you are interested in using the RCON protocol.&lt;br /&gt;
&lt;br /&gt;
For example, given a virtual machine with an IP address of &amp;lt;tt&amp;gt;10.0.2.15&amp;lt;/tt&amp;gt; and the server listening on port 27015, you should configure NAT as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt; (host) &amp;amp;rarr; &amp;lt;tt&amp;gt;10.0.2.15:27015&amp;lt;/tt&amp;gt; (guest)&lt;br /&gt;
&lt;br /&gt;
You can then connect to the server from the host OS by connecting to &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Any loopback IP address on the host portion is acceptable to use (that is, any address starting with &amp;lt;tt&amp;gt;127.*.*.*&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Host-Only Adapter ====&lt;br /&gt;
&lt;br /&gt;
Enable the Host-Only Adapter on your VM and statically assign the address to be in the same network as your host operating system's adapter. This allows you to connect to the server without any additional networking complexities.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11447</id>
		<title>User:Nosoop/Guide/Game Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11447"/>
		<updated>2023-07-15T05:31:16Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Using Workshop maps */ Convert heading to use note&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine games often differ in configuration; here are some basic suggestions on how to set them up for either testing or production use.&lt;br /&gt;
&lt;br /&gt;
= General =&lt;br /&gt;
&lt;br /&gt;
The following section(s) apply to most, if not all games.&lt;br /&gt;
&lt;br /&gt;
== Fast Downloads ==&lt;br /&gt;
&lt;br /&gt;
The Source Engine normally provides downloads over the same channel as gameplay, which is rather slow.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;quot;Fast&amp;amp;quot; downloads are downloads served out-of-band over HTTP, and as such you will need to have a web (HTTP) server up and running to take advantage of this functionality.  This is highly recommended if you are running a server with any amount of custom content that a player needs to download (models, sounds, maps).&lt;br /&gt;
&lt;br /&gt;
If you're using a game server provider, you may already have access to a web server for fast download purposes; check with your provider to confirm.&lt;br /&gt;
&lt;br /&gt;
Examples of web servers include: [https://www.nginx.com/ nginx], [https://caddyserver.com/ Caddy], [https://httpd.apache.org/ Apache], [https://www.rejetto.com/hfs/ HFS], and [https://en.wikipedia.org/wiki/Comparison_of_web_server_software many others] (and many more not included in that list).&lt;br /&gt;
&lt;br /&gt;
Once you have an HTTP server running, configure &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_downloadurl &amp;amp;quot;http://{your_server_location}/{path}&amp;amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The URL must be quoted, as &amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; is treated as the start of a comment and if left unquoted, the rest of the line will be ignored.  Do not include a trailing slash &amp;amp;mdash; the game client adds one when making the request; web servers are not guaranteed to collapse double slashes in the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;{path}&amp;lt;/tt&amp;gt; should be the path on your server that would translate to the root of your game server.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a file &amp;lt;tt&amp;gt;sound/my_server/fart.mp3&amp;lt;/tt&amp;gt; and an &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;, the client will request &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads/sound/my_server/fart.mp3&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; (and its BZip2-compressed equivalent).&lt;br /&gt;
&lt;br /&gt;
You will need to also copy the files from the game server to the web server.&lt;br /&gt;
&lt;br /&gt;
== SourceMod extension not loading ==&lt;br /&gt;
&lt;br /&gt;
By default, if no plugin depends on an extension, it won't be loaded automatically, nor will it show up in &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;sm exts load ${extension}&amp;lt;/tt&amp;gt; if you'd like to test if it loads and to see if it fails, or add an &amp;lt;tt&amp;gt;${extension}.autoload&amp;lt;/tt&amp;gt; file (empty or not) in the extensions directory if you always want it to load.&lt;br /&gt;
&lt;br /&gt;
== RCON ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Source_RCON_Protocol Source RCON Protocol] allows users to remotely issue console commands to dedicated server instances.&lt;br /&gt;
&lt;br /&gt;
You likely won't need this, because you can issue console commands through&lt;br /&gt;
&lt;br /&gt;
* running the server instance in a terminal multiplexer session (with &amp;lt;tt&amp;gt;screen&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;tmux&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* your game server provider providing a web interface that provides real-time console input and output&lt;br /&gt;
&lt;br /&gt;
If you have full access to the machine that your server runs on, you can block RCON packets by dropping TCP packets going to the game port entirely.&lt;br /&gt;
&lt;br /&gt;
Note that doing so will also prevent use of third-party extensions that process TCP connections on the game port, such as [https://forums.alliedmods.net/showthread.php?t=270962 Conplex].&lt;br /&gt;
&lt;br /&gt;
You can use the following on Linux, if you are using iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# the following commands append rules to the firewall; the order here is important&lt;br /&gt;
# change 27015 to the game port&lt;br /&gt;
&lt;br /&gt;
# accept RCON traffic that comes from the same machine, for things like SourceBans&lt;br /&gt;
# if you know you aren't using anything else that relies on RCON you may omit this&lt;br /&gt;
# if legitimate RCON traffic may come from elsewhere, change the source network (-s 127.0.0.1/8),&lt;br /&gt;
# or append additional rules for addresses that should be allowed&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -s 127.0.0.1/8 -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
# drop everything else going to the game port&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Platform-specific =&lt;br /&gt;
&lt;br /&gt;
== Linux extension failing to load on outdated &amp;lt;tt&amp;gt;GLIBCXX_*&amp;lt;/tt&amp;gt; version ==&lt;br /&gt;
&lt;br /&gt;
Various Source Engine games (Counter Strike: Source, Day of Defeat: Source, Counter Strike: Global Offensive, third-party games using the Source SDK modding system, possibly others) bundle standard libraries that are older than what current operating systems ship with, but newer than those that Valve ships as a baseline.&lt;br /&gt;
&lt;br /&gt;
Software that depends on new versions of libraries will fail to load.  This includes Metamod:Source, SourceMod, and other native code / plugins / extension.&lt;br /&gt;
&lt;br /&gt;
You can choose to do one of the following:&lt;br /&gt;
&lt;br /&gt;
* Remove any existing copies of &amp;lt;tt&amp;gt;bin/libstdc++.so.6&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to your game install directory (not the root of the filesytem); this will let the game load the system libraries.&lt;br /&gt;
** If you are on a 64-bit system, continue to the [[#64-bit_Linux_systems_and_32-bit_executables|next section]] to ensure the system's 32-bit libraries are actually available after removing the Valve-bundled copies.&lt;br /&gt;
* If your operating system is also dated, you will need rebuild the extension using an older build environment, or upgrade to a newer one.  If you plan on recompiling the extension, the [https://github.com/ValveSoftware/steam-runtime Steam Runtime SDK] is considered the baseline of support.&lt;br /&gt;
&lt;br /&gt;
== 64-bit Linux systems and 32-bit executables ==&lt;br /&gt;
&lt;br /&gt;
[https://sporks.space/2022/02/27/win32-is-the-stable-linux-userland-abi-and-the-consequences/ Unlike Windows], 64-bit Linux systems are not guaranteed to ship with full compatibility for 32-bit executables by default.&lt;br /&gt;
&lt;br /&gt;
Depending on your distribution, you will need to run one of the following commands as root to install the required packages / libraries:&lt;br /&gt;
&lt;br /&gt;
* Debian / Ubuntu: &amp;lt;tt&amp;gt;apt install gcc-multilib lib32z1&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Arch: &amp;lt;tt&amp;gt;pacman -S lib32-gcc-libs lib32-zlib&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Fedora: &amp;lt;tt&amp;gt;yum -y install glibc.i686 zlib.i686&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Game Specific =&lt;br /&gt;
&lt;br /&gt;
== Team Fortress 2 ==&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.teamfortress.com/wiki/Dedicated_server_configuration Dedicated server configuration] section on the Team Fortress 2 Official Wiki provides general configuration instructions.  Depending on the platform you're working on, you may also be interested in the sections for [https://wiki.teamfortress.com/wiki/Linux_dedicated_server Linux] and [https://wiki.teamfortress.com/wiki/Windows_dedicated_server Windows].&lt;br /&gt;
&lt;br /&gt;
=== Mann vs. Machine ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;tt&amp;gt;tf_mvm_min_players_to_start&amp;lt;/tt&amp;gt; to 1 to only require one player to ready up and start the mission.&lt;br /&gt;
&lt;br /&gt;
=== Steam Datagram Relay ===&lt;br /&gt;
&lt;br /&gt;
The Steam Datagram Relay routes both server and client connections through the Steam network, hiding the IP address of each from the other.&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;tt&amp;gt;-enablefakeip&amp;lt;/tt&amp;gt; in the server's launch options to enable.  The server will then report &amp;quot;FakeIP allocation succeeded&amp;quot; at the end of startup; use that IP address / port combination in your game client to connect to the server.  This allocation will change on every server startup.&lt;br /&gt;
&lt;br /&gt;
=== Using Workshop maps ===&lt;br /&gt;
&lt;br /&gt;
{{note|This section has instructions specific to Team Fortress 2, and will likely not carry over to other games such as Counter-Strike: Global Offensive.}}&lt;br /&gt;
&lt;br /&gt;
[https://www.teamfortress.com/post.php?id=17214 As described in the patch notes shortly after the feature was added], Valve's intent is for server operators to use map names in the form &amp;lt;tt&amp;gt;workshop/${mapid}&amp;lt;/tt&amp;gt;, where &amp;lt;tt&amp;gt;${mapid}&amp;lt;/tt&amp;gt; is the ID of the map in the Workshop.   For example, [https://steamcommunity.com/sharedfiles/filedetails/?id=619869471 Sulfur] has an ID of 619869471, so you would specify it as &amp;lt;tt&amp;gt;workshop/619869471&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This allows both the game server and any connected clients to retrieve the map through Steam.&lt;br /&gt;
&lt;br /&gt;
You can use that form in any place that accepts maps, such as the &amp;lt;tt&amp;gt;map&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;changelevel&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nextlevel&amp;lt;/tt&amp;gt; commands as well as the mapcycle file.  SourceMod itself has support to translate the names to their display forms and will do so in first-party plugins; third-party plugins may or may not support this functionality.&lt;br /&gt;
&lt;br /&gt;
Disregard any suggestions to subscribe to the map and copy the file to your game / fast download servers.  That is often repeated, yet bad advice.&lt;br /&gt;
&lt;br /&gt;
=== Games that aren't ===&lt;br /&gt;
&lt;br /&gt;
Non-exhaustive list of Source Engine class-based shooters with a cartoon-like visual style based on the art of Dean Cornwell, J. C. Leyendecker, and Norman Rockwell, that aren't [https://store.steampowered.com/app/440/Team_Fortress_2/ Team Fortress 2]:&lt;br /&gt;
&lt;br /&gt;
* Team Fortress 2 Classic&lt;br /&gt;
* Open Fortress&lt;br /&gt;
&lt;br /&gt;
If you're developing plugins and asking questions about one of those games, please specifically name them.  These games are not guaranteed to behave the same as &amp;quot;retail&amp;quot; Team Fortress 2, and solutions that work for retail aren't guaranteed to work on third-party mods.&lt;br /&gt;
&lt;br /&gt;
== Counter-Strike: Global Offensive ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Dedicated_Servers#Advanced_Configuration Advanced Configuration] section on the Valve Developer Wiki describes server configuration unique to CS:GO. It's different from most other mods.&lt;br /&gt;
&lt;br /&gt;
=== Responsive server console when hibernating ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;sv_hibernate_ms&amp;lt;/code&amp;gt; to 0 to make the server console more responsive when no players are online.&lt;br /&gt;
&lt;br /&gt;
== Left 4 Dead 2 ==&lt;br /&gt;
&lt;br /&gt;
=== Disabling lobby system ===&lt;br /&gt;
&lt;br /&gt;
While developing plugins, you generally don't want players being connected through Steam's lobby system.  Add the following to &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_allow_lobby_connect_only &amp;quot;0&amp;quot;;&lt;br /&gt;
sv_password &amp;quot;password_to_connect_with&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Virtual Server Configuration =&lt;br /&gt;
&lt;br /&gt;
As a developer, you may need to test on multiple platforms. To avoid having another physical machine to work on, you can use virtualization to run an operating system on your desktop.&lt;br /&gt;
&lt;br /&gt;
== Virtualbox ==&lt;br /&gt;
&lt;br /&gt;
=== Networking ===&lt;br /&gt;
&lt;br /&gt;
==== Network Address Translation ====&lt;br /&gt;
&lt;br /&gt;
With NAT plus port forwarding, the minimum would be to forward UDP from one of the host's loopback IP addresses to the server port on the VM's address.  Forwarding TCP isn't necessary unless you are interested in using the RCON protocol.&lt;br /&gt;
&lt;br /&gt;
For example, given a virtual machine with an IP address of &amp;lt;tt&amp;gt;10.0.2.15&amp;lt;/tt&amp;gt; and the server listening on port 27015, you should configure NAT as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt; (host) &amp;amp;rarr; &amp;lt;tt&amp;gt;10.0.2.15:27015&amp;lt;/tt&amp;gt; (guest)&lt;br /&gt;
&lt;br /&gt;
You can then connect to the server from the host OS by connecting to &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Any loopback IP address on the host portion is acceptable to use (that is, any address starting with &amp;lt;tt&amp;gt;127.*.*.*&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Host-Only Adapter ====&lt;br /&gt;
&lt;br /&gt;
Enable the Host-Only Adapter on your VM and statically assign the address to be in the same network as your host operating system's adapter. This allows you to connect to the server without any additional networking complexities.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11446</id>
		<title>User:Nosoop/Guide/Game Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11446"/>
		<updated>2023-07-15T05:29:35Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Using Workshop maps */ Reword TF2-specific heading&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine games often differ in configuration; here are some basic suggestions on how to set them up for either testing or production use.&lt;br /&gt;
&lt;br /&gt;
= General =&lt;br /&gt;
&lt;br /&gt;
The following section(s) apply to most, if not all games.&lt;br /&gt;
&lt;br /&gt;
== Fast Downloads ==&lt;br /&gt;
&lt;br /&gt;
The Source Engine normally provides downloads over the same channel as gameplay, which is rather slow.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;quot;Fast&amp;amp;quot; downloads are downloads served out-of-band over HTTP, and as such you will need to have a web (HTTP) server up and running to take advantage of this functionality.  This is highly recommended if you are running a server with any amount of custom content that a player needs to download (models, sounds, maps).&lt;br /&gt;
&lt;br /&gt;
If you're using a game server provider, you may already have access to a web server for fast download purposes; check with your provider to confirm.&lt;br /&gt;
&lt;br /&gt;
Examples of web servers include: [https://www.nginx.com/ nginx], [https://caddyserver.com/ Caddy], [https://httpd.apache.org/ Apache], [https://www.rejetto.com/hfs/ HFS], and [https://en.wikipedia.org/wiki/Comparison_of_web_server_software many others] (and many more not included in that list).&lt;br /&gt;
&lt;br /&gt;
Once you have an HTTP server running, configure &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_downloadurl &amp;amp;quot;http://{your_server_location}/{path}&amp;amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The URL must be quoted, as &amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; is treated as the start of a comment and if left unquoted, the rest of the line will be ignored.  Do not include a trailing slash &amp;amp;mdash; the game client adds one when making the request; web servers are not guaranteed to collapse double slashes in the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;{path}&amp;lt;/tt&amp;gt; should be the path on your server that would translate to the root of your game server.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a file &amp;lt;tt&amp;gt;sound/my_server/fart.mp3&amp;lt;/tt&amp;gt; and an &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;, the client will request &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads/sound/my_server/fart.mp3&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; (and its BZip2-compressed equivalent).&lt;br /&gt;
&lt;br /&gt;
You will need to also copy the files from the game server to the web server.&lt;br /&gt;
&lt;br /&gt;
== SourceMod extension not loading ==&lt;br /&gt;
&lt;br /&gt;
By default, if no plugin depends on an extension, it won't be loaded automatically, nor will it show up in &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;sm exts load ${extension}&amp;lt;/tt&amp;gt; if you'd like to test if it loads and to see if it fails, or add an &amp;lt;tt&amp;gt;${extension}.autoload&amp;lt;/tt&amp;gt; file (empty or not) in the extensions directory if you always want it to load.&lt;br /&gt;
&lt;br /&gt;
== RCON ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Source_RCON_Protocol Source RCON Protocol] allows users to remotely issue console commands to dedicated server instances.&lt;br /&gt;
&lt;br /&gt;
You likely won't need this, because you can issue console commands through&lt;br /&gt;
&lt;br /&gt;
* running the server instance in a terminal multiplexer session (with &amp;lt;tt&amp;gt;screen&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;tmux&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* your game server provider providing a web interface that provides real-time console input and output&lt;br /&gt;
&lt;br /&gt;
If you have full access to the machine that your server runs on, you can block RCON packets by dropping TCP packets going to the game port entirely.&lt;br /&gt;
&lt;br /&gt;
Note that doing so will also prevent use of third-party extensions that process TCP connections on the game port, such as [https://forums.alliedmods.net/showthread.php?t=270962 Conplex].&lt;br /&gt;
&lt;br /&gt;
You can use the following on Linux, if you are using iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# the following commands append rules to the firewall; the order here is important&lt;br /&gt;
# change 27015 to the game port&lt;br /&gt;
&lt;br /&gt;
# accept RCON traffic that comes from the same machine, for things like SourceBans&lt;br /&gt;
# if you know you aren't using anything else that relies on RCON you may omit this&lt;br /&gt;
# if legitimate RCON traffic may come from elsewhere, change the source network (-s 127.0.0.1/8),&lt;br /&gt;
# or append additional rules for addresses that should be allowed&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -s 127.0.0.1/8 -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
# drop everything else going to the game port&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Platform-specific =&lt;br /&gt;
&lt;br /&gt;
== Linux extension failing to load on outdated &amp;lt;tt&amp;gt;GLIBCXX_*&amp;lt;/tt&amp;gt; version ==&lt;br /&gt;
&lt;br /&gt;
Various Source Engine games (Counter Strike: Source, Day of Defeat: Source, Counter Strike: Global Offensive, third-party games using the Source SDK modding system, possibly others) bundle standard libraries that are older than what current operating systems ship with, but newer than those that Valve ships as a baseline.&lt;br /&gt;
&lt;br /&gt;
Software that depends on new versions of libraries will fail to load.  This includes Metamod:Source, SourceMod, and other native code / plugins / extension.&lt;br /&gt;
&lt;br /&gt;
You can choose to do one of the following:&lt;br /&gt;
&lt;br /&gt;
* Remove any existing copies of &amp;lt;tt&amp;gt;bin/libstdc++.so.6&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to your game install directory (not the root of the filesytem); this will let the game load the system libraries.&lt;br /&gt;
** If you are on a 64-bit system, continue to the [[#64-bit_Linux_systems_and_32-bit_executables|next section]] to ensure the system's 32-bit libraries are actually available after removing the Valve-bundled copies.&lt;br /&gt;
* If your operating system is also dated, you will need rebuild the extension using an older build environment, or upgrade to a newer one.  If you plan on recompiling the extension, the [https://github.com/ValveSoftware/steam-runtime Steam Runtime SDK] is considered the baseline of support.&lt;br /&gt;
&lt;br /&gt;
== 64-bit Linux systems and 32-bit executables ==&lt;br /&gt;
&lt;br /&gt;
[https://sporks.space/2022/02/27/win32-is-the-stable-linux-userland-abi-and-the-consequences/ Unlike Windows], 64-bit Linux systems are not guaranteed to ship with full compatibility for 32-bit executables by default.&lt;br /&gt;
&lt;br /&gt;
Depending on your distribution, you will need to run one of the following commands as root to install the required packages / libraries:&lt;br /&gt;
&lt;br /&gt;
* Debian / Ubuntu: &amp;lt;tt&amp;gt;apt install gcc-multilib lib32z1&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Arch: &amp;lt;tt&amp;gt;pacman -S lib32-gcc-libs lib32-zlib&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Fedora: &amp;lt;tt&amp;gt;yum -y install glibc.i686 zlib.i686&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Game Specific =&lt;br /&gt;
&lt;br /&gt;
== Team Fortress 2 ==&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.teamfortress.com/wiki/Dedicated_server_configuration Dedicated server configuration] section on the Team Fortress 2 Official Wiki provides general configuration instructions.  Depending on the platform you're working on, you may also be interested in the sections for [https://wiki.teamfortress.com/wiki/Linux_dedicated_server Linux] and [https://wiki.teamfortress.com/wiki/Windows_dedicated_server Windows].&lt;br /&gt;
&lt;br /&gt;
=== Mann vs. Machine ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;tt&amp;gt;tf_mvm_min_players_to_start&amp;lt;/tt&amp;gt; to 1 to only require one player to ready up and start the mission.&lt;br /&gt;
&lt;br /&gt;
=== Steam Datagram Relay ===&lt;br /&gt;
&lt;br /&gt;
The Steam Datagram Relay routes both server and client connections through the Steam network, hiding the IP address of each from the other.&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;tt&amp;gt;-enablefakeip&amp;lt;/tt&amp;gt; in the server's launch options to enable.  The server will then report &amp;quot;FakeIP allocation succeeded&amp;quot; at the end of startup; use that IP address / port combination in your game client to connect to the server.  This allocation will change on every server startup.&lt;br /&gt;
&lt;br /&gt;
=== Using Workshop maps ===&lt;br /&gt;
&lt;br /&gt;
(This section has instructions specific to Team Fortress 2, and will likely not carry over to other games such as Counter-Strike: Global Offensive.)&lt;br /&gt;
&lt;br /&gt;
[https://www.teamfortress.com/post.php?id=17214 As described in the patch notes shortly after the feature was added], Valve's intent is for server operators to use map names in the form &amp;lt;tt&amp;gt;workshop/${mapid}&amp;lt;/tt&amp;gt;, where &amp;lt;tt&amp;gt;${mapid}&amp;lt;/tt&amp;gt; is the ID of the map in the Workshop.   For example, [https://steamcommunity.com/sharedfiles/filedetails/?id=619869471 Sulfur] has an ID of 619869471, so you would specify it as &amp;lt;tt&amp;gt;workshop/619869471&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This allows both the game server and any connected clients to retrieve the map through Steam.&lt;br /&gt;
&lt;br /&gt;
You can use that form in any place that accepts maps, such as the &amp;lt;tt&amp;gt;map&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;changelevel&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nextlevel&amp;lt;/tt&amp;gt; commands as well as the mapcycle file.  SourceMod itself has support to translate the names to their display forms and will do so in first-party plugins; third-party plugins may or may not support this functionality.&lt;br /&gt;
&lt;br /&gt;
Disregard any suggestions to subscribe to the map and copy the file to your game / fast download servers.  That is often repeated, yet bad advice.&lt;br /&gt;
&lt;br /&gt;
=== Games that aren't ===&lt;br /&gt;
&lt;br /&gt;
Non-exhaustive list of Source Engine class-based shooters with a cartoon-like visual style based on the art of Dean Cornwell, J. C. Leyendecker, and Norman Rockwell, that aren't [https://store.steampowered.com/app/440/Team_Fortress_2/ Team Fortress 2]:&lt;br /&gt;
&lt;br /&gt;
* Team Fortress 2 Classic&lt;br /&gt;
* Open Fortress&lt;br /&gt;
&lt;br /&gt;
If you're developing plugins and asking questions about one of those games, please specifically name them.  These games are not guaranteed to behave the same as &amp;quot;retail&amp;quot; Team Fortress 2, and solutions that work for retail aren't guaranteed to work on third-party mods.&lt;br /&gt;
&lt;br /&gt;
== Counter-Strike: Global Offensive ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Dedicated_Servers#Advanced_Configuration Advanced Configuration] section on the Valve Developer Wiki describes server configuration unique to CS:GO. It's different from most other mods.&lt;br /&gt;
&lt;br /&gt;
=== Responsive server console when hibernating ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;sv_hibernate_ms&amp;lt;/code&amp;gt; to 0 to make the server console more responsive when no players are online.&lt;br /&gt;
&lt;br /&gt;
== Left 4 Dead 2 ==&lt;br /&gt;
&lt;br /&gt;
=== Disabling lobby system ===&lt;br /&gt;
&lt;br /&gt;
While developing plugins, you generally don't want players being connected through Steam's lobby system.  Add the following to &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_allow_lobby_connect_only &amp;quot;0&amp;quot;;&lt;br /&gt;
sv_password &amp;quot;password_to_connect_with&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Virtual Server Configuration =&lt;br /&gt;
&lt;br /&gt;
As a developer, you may need to test on multiple platforms. To avoid having another physical machine to work on, you can use virtualization to run an operating system on your desktop.&lt;br /&gt;
&lt;br /&gt;
== Virtualbox ==&lt;br /&gt;
&lt;br /&gt;
=== Networking ===&lt;br /&gt;
&lt;br /&gt;
==== Network Address Translation ====&lt;br /&gt;
&lt;br /&gt;
With NAT plus port forwarding, the minimum would be to forward UDP from one of the host's loopback IP addresses to the server port on the VM's address.  Forwarding TCP isn't necessary unless you are interested in using the RCON protocol.&lt;br /&gt;
&lt;br /&gt;
For example, given a virtual machine with an IP address of &amp;lt;tt&amp;gt;10.0.2.15&amp;lt;/tt&amp;gt; and the server listening on port 27015, you should configure NAT as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt; (host) &amp;amp;rarr; &amp;lt;tt&amp;gt;10.0.2.15:27015&amp;lt;/tt&amp;gt; (guest)&lt;br /&gt;
&lt;br /&gt;
You can then connect to the server from the host OS by connecting to &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Any loopback IP address on the host portion is acceptable to use (that is, any address starting with &amp;lt;tt&amp;gt;127.*.*.*&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Host-Only Adapter ====&lt;br /&gt;
&lt;br /&gt;
Enable the Host-Only Adapter on your VM and statically assign the address to be in the same network as your host operating system's adapter. This allows you to connect to the server without any additional networking complexities.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11445</id>
		<title>User:Nosoop/Guide/Game Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11445"/>
		<updated>2023-07-15T05:27:44Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Using Workshop maps */ Add note that this is TF2-specific&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine games often differ in configuration; here are some basic suggestions on how to set them up for either testing or production use.&lt;br /&gt;
&lt;br /&gt;
= General =&lt;br /&gt;
&lt;br /&gt;
The following section(s) apply to most, if not all games.&lt;br /&gt;
&lt;br /&gt;
== Fast Downloads ==&lt;br /&gt;
&lt;br /&gt;
The Source Engine normally provides downloads over the same channel as gameplay, which is rather slow.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;quot;Fast&amp;amp;quot; downloads are downloads served out-of-band over HTTP, and as such you will need to have a web (HTTP) server up and running to take advantage of this functionality.  This is highly recommended if you are running a server with any amount of custom content that a player needs to download (models, sounds, maps).&lt;br /&gt;
&lt;br /&gt;
If you're using a game server provider, you may already have access to a web server for fast download purposes; check with your provider to confirm.&lt;br /&gt;
&lt;br /&gt;
Examples of web servers include: [https://www.nginx.com/ nginx], [https://caddyserver.com/ Caddy], [https://httpd.apache.org/ Apache], [https://www.rejetto.com/hfs/ HFS], and [https://en.wikipedia.org/wiki/Comparison_of_web_server_software many others] (and many more not included in that list).&lt;br /&gt;
&lt;br /&gt;
Once you have an HTTP server running, configure &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_downloadurl &amp;amp;quot;http://{your_server_location}/{path}&amp;amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The URL must be quoted, as &amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; is treated as the start of a comment and if left unquoted, the rest of the line will be ignored.  Do not include a trailing slash &amp;amp;mdash; the game client adds one when making the request; web servers are not guaranteed to collapse double slashes in the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;{path}&amp;lt;/tt&amp;gt; should be the path on your server that would translate to the root of your game server.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a file &amp;lt;tt&amp;gt;sound/my_server/fart.mp3&amp;lt;/tt&amp;gt; and an &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;, the client will request &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads/sound/my_server/fart.mp3&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; (and its BZip2-compressed equivalent).&lt;br /&gt;
&lt;br /&gt;
You will need to also copy the files from the game server to the web server.&lt;br /&gt;
&lt;br /&gt;
== SourceMod extension not loading ==&lt;br /&gt;
&lt;br /&gt;
By default, if no plugin depends on an extension, it won't be loaded automatically, nor will it show up in &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;sm exts load ${extension}&amp;lt;/tt&amp;gt; if you'd like to test if it loads and to see if it fails, or add an &amp;lt;tt&amp;gt;${extension}.autoload&amp;lt;/tt&amp;gt; file (empty or not) in the extensions directory if you always want it to load.&lt;br /&gt;
&lt;br /&gt;
== RCON ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Source_RCON_Protocol Source RCON Protocol] allows users to remotely issue console commands to dedicated server instances.&lt;br /&gt;
&lt;br /&gt;
You likely won't need this, because you can issue console commands through&lt;br /&gt;
&lt;br /&gt;
* running the server instance in a terminal multiplexer session (with &amp;lt;tt&amp;gt;screen&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;tmux&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* your game server provider providing a web interface that provides real-time console input and output&lt;br /&gt;
&lt;br /&gt;
If you have full access to the machine that your server runs on, you can block RCON packets by dropping TCP packets going to the game port entirely.&lt;br /&gt;
&lt;br /&gt;
Note that doing so will also prevent use of third-party extensions that process TCP connections on the game port, such as [https://forums.alliedmods.net/showthread.php?t=270962 Conplex].&lt;br /&gt;
&lt;br /&gt;
You can use the following on Linux, if you are using iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# the following commands append rules to the firewall; the order here is important&lt;br /&gt;
# change 27015 to the game port&lt;br /&gt;
&lt;br /&gt;
# accept RCON traffic that comes from the same machine, for things like SourceBans&lt;br /&gt;
# if you know you aren't using anything else that relies on RCON you may omit this&lt;br /&gt;
# if legitimate RCON traffic may come from elsewhere, change the source network (-s 127.0.0.1/8),&lt;br /&gt;
# or append additional rules for addresses that should be allowed&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -s 127.0.0.1/8 -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
# drop everything else going to the game port&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Platform-specific =&lt;br /&gt;
&lt;br /&gt;
== Linux extension failing to load on outdated &amp;lt;tt&amp;gt;GLIBCXX_*&amp;lt;/tt&amp;gt; version ==&lt;br /&gt;
&lt;br /&gt;
Various Source Engine games (Counter Strike: Source, Day of Defeat: Source, Counter Strike: Global Offensive, third-party games using the Source SDK modding system, possibly others) bundle standard libraries that are older than what current operating systems ship with, but newer than those that Valve ships as a baseline.&lt;br /&gt;
&lt;br /&gt;
Software that depends on new versions of libraries will fail to load.  This includes Metamod:Source, SourceMod, and other native code / plugins / extension.&lt;br /&gt;
&lt;br /&gt;
You can choose to do one of the following:&lt;br /&gt;
&lt;br /&gt;
* Remove any existing copies of &amp;lt;tt&amp;gt;bin/libstdc++.so.6&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to your game install directory (not the root of the filesytem); this will let the game load the system libraries.&lt;br /&gt;
** If you are on a 64-bit system, continue to the [[#64-bit_Linux_systems_and_32-bit_executables|next section]] to ensure the system's 32-bit libraries are actually available after removing the Valve-bundled copies.&lt;br /&gt;
* If your operating system is also dated, you will need rebuild the extension using an older build environment, or upgrade to a newer one.  If you plan on recompiling the extension, the [https://github.com/ValveSoftware/steam-runtime Steam Runtime SDK] is considered the baseline of support.&lt;br /&gt;
&lt;br /&gt;
== 64-bit Linux systems and 32-bit executables ==&lt;br /&gt;
&lt;br /&gt;
[https://sporks.space/2022/02/27/win32-is-the-stable-linux-userland-abi-and-the-consequences/ Unlike Windows], 64-bit Linux systems are not guaranteed to ship with full compatibility for 32-bit executables by default.&lt;br /&gt;
&lt;br /&gt;
Depending on your distribution, you will need to run one of the following commands as root to install the required packages / libraries:&lt;br /&gt;
&lt;br /&gt;
* Debian / Ubuntu: &amp;lt;tt&amp;gt;apt install gcc-multilib lib32z1&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Arch: &amp;lt;tt&amp;gt;pacman -S lib32-gcc-libs lib32-zlib&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Fedora: &amp;lt;tt&amp;gt;yum -y install glibc.i686 zlib.i686&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Game Specific =&lt;br /&gt;
&lt;br /&gt;
== Team Fortress 2 ==&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.teamfortress.com/wiki/Dedicated_server_configuration Dedicated server configuration] section on the Team Fortress 2 Official Wiki provides general configuration instructions.  Depending on the platform you're working on, you may also be interested in the sections for [https://wiki.teamfortress.com/wiki/Linux_dedicated_server Linux] and [https://wiki.teamfortress.com/wiki/Windows_dedicated_server Windows].&lt;br /&gt;
&lt;br /&gt;
=== Mann vs. Machine ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;tt&amp;gt;tf_mvm_min_players_to_start&amp;lt;/tt&amp;gt; to 1 to only require one player to ready up and start the mission.&lt;br /&gt;
&lt;br /&gt;
=== Steam Datagram Relay ===&lt;br /&gt;
&lt;br /&gt;
The Steam Datagram Relay routes both server and client connections through the Steam network, hiding the IP address of each from the other.&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;tt&amp;gt;-enablefakeip&amp;lt;/tt&amp;gt; in the server's launch options to enable.  The server will then report &amp;quot;FakeIP allocation succeeded&amp;quot; at the end of startup; use that IP address / port combination in your game client to connect to the server.  This allocation will change on every server startup.&lt;br /&gt;
&lt;br /&gt;
=== Using Workshop maps ===&lt;br /&gt;
&lt;br /&gt;
(This are instructions specific to Team Fortress 2; other games such as Counter-Strike: Global Offensive may have different instructions.)&lt;br /&gt;
&lt;br /&gt;
[https://www.teamfortress.com/post.php?id=17214 As described in the patch notes shortly after the feature was added], Valve's intent is for server operators to use map names in the form &amp;lt;tt&amp;gt;workshop/${mapid}&amp;lt;/tt&amp;gt;, where &amp;lt;tt&amp;gt;${mapid}&amp;lt;/tt&amp;gt; is the ID of the map in the Workshop.   For example, [https://steamcommunity.com/sharedfiles/filedetails/?id=619869471 Sulfur] has an ID of 619869471, so you would specify it as &amp;lt;tt&amp;gt;workshop/619869471&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This allows both the game server and any connected clients to retrieve the map through Steam.&lt;br /&gt;
&lt;br /&gt;
You can use that form in any place that accepts maps, such as the &amp;lt;tt&amp;gt;map&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;changelevel&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nextlevel&amp;lt;/tt&amp;gt; commands as well as the mapcycle file.  SourceMod itself has support to translate the names to their display forms and will do so in first-party plugins; third-party plugins may or may not support this functionality.&lt;br /&gt;
&lt;br /&gt;
Disregard any suggestions to subscribe to the map and copy the file to your game / fast download servers.  That is often repeated, yet bad advice.&lt;br /&gt;
&lt;br /&gt;
=== Games that aren't ===&lt;br /&gt;
&lt;br /&gt;
Non-exhaustive list of Source Engine class-based shooters with a cartoon-like visual style based on the art of Dean Cornwell, J. C. Leyendecker, and Norman Rockwell, that aren't [https://store.steampowered.com/app/440/Team_Fortress_2/ Team Fortress 2]:&lt;br /&gt;
&lt;br /&gt;
* Team Fortress 2 Classic&lt;br /&gt;
* Open Fortress&lt;br /&gt;
&lt;br /&gt;
If you're developing plugins and asking questions about one of those games, please specifically name them.  These games are not guaranteed to behave the same as &amp;quot;retail&amp;quot; Team Fortress 2, and solutions that work for retail aren't guaranteed to work on third-party mods.&lt;br /&gt;
&lt;br /&gt;
== Counter-Strike: Global Offensive ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Dedicated_Servers#Advanced_Configuration Advanced Configuration] section on the Valve Developer Wiki describes server configuration unique to CS:GO. It's different from most other mods.&lt;br /&gt;
&lt;br /&gt;
=== Responsive server console when hibernating ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;sv_hibernate_ms&amp;lt;/code&amp;gt; to 0 to make the server console more responsive when no players are online.&lt;br /&gt;
&lt;br /&gt;
== Left 4 Dead 2 ==&lt;br /&gt;
&lt;br /&gt;
=== Disabling lobby system ===&lt;br /&gt;
&lt;br /&gt;
While developing plugins, you generally don't want players being connected through Steam's lobby system.  Add the following to &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_allow_lobby_connect_only &amp;quot;0&amp;quot;;&lt;br /&gt;
sv_password &amp;quot;password_to_connect_with&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Virtual Server Configuration =&lt;br /&gt;
&lt;br /&gt;
As a developer, you may need to test on multiple platforms. To avoid having another physical machine to work on, you can use virtualization to run an operating system on your desktop.&lt;br /&gt;
&lt;br /&gt;
== Virtualbox ==&lt;br /&gt;
&lt;br /&gt;
=== Networking ===&lt;br /&gt;
&lt;br /&gt;
==== Network Address Translation ====&lt;br /&gt;
&lt;br /&gt;
With NAT plus port forwarding, the minimum would be to forward UDP from one of the host's loopback IP addresses to the server port on the VM's address.  Forwarding TCP isn't necessary unless you are interested in using the RCON protocol.&lt;br /&gt;
&lt;br /&gt;
For example, given a virtual machine with an IP address of &amp;lt;tt&amp;gt;10.0.2.15&amp;lt;/tt&amp;gt; and the server listening on port 27015, you should configure NAT as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt; (host) &amp;amp;rarr; &amp;lt;tt&amp;gt;10.0.2.15:27015&amp;lt;/tt&amp;gt; (guest)&lt;br /&gt;
&lt;br /&gt;
You can then connect to the server from the host OS by connecting to &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Any loopback IP address on the host portion is acceptable to use (that is, any address starting with &amp;lt;tt&amp;gt;127.*.*.*&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Host-Only Adapter ====&lt;br /&gt;
&lt;br /&gt;
Enable the Host-Only Adapter on your VM and statically assign the address to be in the same network as your host operating system's adapter. This allows you to connect to the server without any additional networking complexities.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11444</id>
		<title>User:Nosoop/Guide/Game Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11444"/>
		<updated>2023-07-15T05:26:16Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Team Fortress 2 */ Add section on using Workshop maps&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine games often differ in configuration; here are some basic suggestions on how to set them up for either testing or production use.&lt;br /&gt;
&lt;br /&gt;
= General =&lt;br /&gt;
&lt;br /&gt;
The following section(s) apply to most, if not all games.&lt;br /&gt;
&lt;br /&gt;
== Fast Downloads ==&lt;br /&gt;
&lt;br /&gt;
The Source Engine normally provides downloads over the same channel as gameplay, which is rather slow.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;quot;Fast&amp;amp;quot; downloads are downloads served out-of-band over HTTP, and as such you will need to have a web (HTTP) server up and running to take advantage of this functionality.  This is highly recommended if you are running a server with any amount of custom content that a player needs to download (models, sounds, maps).&lt;br /&gt;
&lt;br /&gt;
If you're using a game server provider, you may already have access to a web server for fast download purposes; check with your provider to confirm.&lt;br /&gt;
&lt;br /&gt;
Examples of web servers include: [https://www.nginx.com/ nginx], [https://caddyserver.com/ Caddy], [https://httpd.apache.org/ Apache], [https://www.rejetto.com/hfs/ HFS], and [https://en.wikipedia.org/wiki/Comparison_of_web_server_software many others] (and many more not included in that list).&lt;br /&gt;
&lt;br /&gt;
Once you have an HTTP server running, configure &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_downloadurl &amp;amp;quot;http://{your_server_location}/{path}&amp;amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The URL must be quoted, as &amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; is treated as the start of a comment and if left unquoted, the rest of the line will be ignored.  Do not include a trailing slash &amp;amp;mdash; the game client adds one when making the request; web servers are not guaranteed to collapse double slashes in the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;{path}&amp;lt;/tt&amp;gt; should be the path on your server that would translate to the root of your game server.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a file &amp;lt;tt&amp;gt;sound/my_server/fart.mp3&amp;lt;/tt&amp;gt; and an &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;, the client will request &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads/sound/my_server/fart.mp3&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; (and its BZip2-compressed equivalent).&lt;br /&gt;
&lt;br /&gt;
You will need to also copy the files from the game server to the web server.&lt;br /&gt;
&lt;br /&gt;
== SourceMod extension not loading ==&lt;br /&gt;
&lt;br /&gt;
By default, if no plugin depends on an extension, it won't be loaded automatically, nor will it show up in &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;sm exts load ${extension}&amp;lt;/tt&amp;gt; if you'd like to test if it loads and to see if it fails, or add an &amp;lt;tt&amp;gt;${extension}.autoload&amp;lt;/tt&amp;gt; file (empty or not) in the extensions directory if you always want it to load.&lt;br /&gt;
&lt;br /&gt;
== RCON ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Source_RCON_Protocol Source RCON Protocol] allows users to remotely issue console commands to dedicated server instances.&lt;br /&gt;
&lt;br /&gt;
You likely won't need this, because you can issue console commands through&lt;br /&gt;
&lt;br /&gt;
* running the server instance in a terminal multiplexer session (with &amp;lt;tt&amp;gt;screen&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;tmux&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* your game server provider providing a web interface that provides real-time console input and output&lt;br /&gt;
&lt;br /&gt;
If you have full access to the machine that your server runs on, you can block RCON packets by dropping TCP packets going to the game port entirely.&lt;br /&gt;
&lt;br /&gt;
Note that doing so will also prevent use of third-party extensions that process TCP connections on the game port, such as [https://forums.alliedmods.net/showthread.php?t=270962 Conplex].&lt;br /&gt;
&lt;br /&gt;
You can use the following on Linux, if you are using iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# the following commands append rules to the firewall; the order here is important&lt;br /&gt;
# change 27015 to the game port&lt;br /&gt;
&lt;br /&gt;
# accept RCON traffic that comes from the same machine, for things like SourceBans&lt;br /&gt;
# if you know you aren't using anything else that relies on RCON you may omit this&lt;br /&gt;
# if legitimate RCON traffic may come from elsewhere, change the source network (-s 127.0.0.1/8),&lt;br /&gt;
# or append additional rules for addresses that should be allowed&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -s 127.0.0.1/8 -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
# drop everything else going to the game port&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Platform-specific =&lt;br /&gt;
&lt;br /&gt;
== Linux extension failing to load on outdated &amp;lt;tt&amp;gt;GLIBCXX_*&amp;lt;/tt&amp;gt; version ==&lt;br /&gt;
&lt;br /&gt;
Various Source Engine games (Counter Strike: Source, Day of Defeat: Source, Counter Strike: Global Offensive, third-party games using the Source SDK modding system, possibly others) bundle standard libraries that are older than what current operating systems ship with, but newer than those that Valve ships as a baseline.&lt;br /&gt;
&lt;br /&gt;
Software that depends on new versions of libraries will fail to load.  This includes Metamod:Source, SourceMod, and other native code / plugins / extension.&lt;br /&gt;
&lt;br /&gt;
You can choose to do one of the following:&lt;br /&gt;
&lt;br /&gt;
* Remove any existing copies of &amp;lt;tt&amp;gt;bin/libstdc++.so.6&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to your game install directory (not the root of the filesytem); this will let the game load the system libraries.&lt;br /&gt;
** If you are on a 64-bit system, continue to the [[#64-bit_Linux_systems_and_32-bit_executables|next section]] to ensure the system's 32-bit libraries are actually available after removing the Valve-bundled copies.&lt;br /&gt;
* If your operating system is also dated, you will need rebuild the extension using an older build environment, or upgrade to a newer one.  If you plan on recompiling the extension, the [https://github.com/ValveSoftware/steam-runtime Steam Runtime SDK] is considered the baseline of support.&lt;br /&gt;
&lt;br /&gt;
== 64-bit Linux systems and 32-bit executables ==&lt;br /&gt;
&lt;br /&gt;
[https://sporks.space/2022/02/27/win32-is-the-stable-linux-userland-abi-and-the-consequences/ Unlike Windows], 64-bit Linux systems are not guaranteed to ship with full compatibility for 32-bit executables by default.&lt;br /&gt;
&lt;br /&gt;
Depending on your distribution, you will need to run one of the following commands as root to install the required packages / libraries:&lt;br /&gt;
&lt;br /&gt;
* Debian / Ubuntu: &amp;lt;tt&amp;gt;apt install gcc-multilib lib32z1&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Arch: &amp;lt;tt&amp;gt;pacman -S lib32-gcc-libs lib32-zlib&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Fedora: &amp;lt;tt&amp;gt;yum -y install glibc.i686 zlib.i686&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Game Specific =&lt;br /&gt;
&lt;br /&gt;
== Team Fortress 2 ==&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.teamfortress.com/wiki/Dedicated_server_configuration Dedicated server configuration] section on the Team Fortress 2 Official Wiki provides general configuration instructions.  Depending on the platform you're working on, you may also be interested in the sections for [https://wiki.teamfortress.com/wiki/Linux_dedicated_server Linux] and [https://wiki.teamfortress.com/wiki/Windows_dedicated_server Windows].&lt;br /&gt;
&lt;br /&gt;
=== Mann vs. Machine ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;tt&amp;gt;tf_mvm_min_players_to_start&amp;lt;/tt&amp;gt; to 1 to only require one player to ready up and start the mission.&lt;br /&gt;
&lt;br /&gt;
=== Steam Datagram Relay ===&lt;br /&gt;
&lt;br /&gt;
The Steam Datagram Relay routes both server and client connections through the Steam network, hiding the IP address of each from the other.&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;tt&amp;gt;-enablefakeip&amp;lt;/tt&amp;gt; in the server's launch options to enable.  The server will then report &amp;quot;FakeIP allocation succeeded&amp;quot; at the end of startup; use that IP address / port combination in your game client to connect to the server.  This allocation will change on every server startup.&lt;br /&gt;
&lt;br /&gt;
=== Using Workshop maps ===&lt;br /&gt;
&lt;br /&gt;
[https://www.teamfortress.com/post.php?id=17214 As described in the patch notes shortly after the feature was added], Valve's intent is for server operators to use map names in the form &amp;lt;tt&amp;gt;workshop/${mapid}&amp;lt;/tt&amp;gt;, where &amp;lt;tt&amp;gt;${mapid}&amp;lt;/tt&amp;gt; is the ID of the map in the Workshop.   For example, [https://steamcommunity.com/sharedfiles/filedetails/?id=619869471 Sulfur] has an ID of 619869471, so you would specify it as &amp;lt;tt&amp;gt;workshop/619869471&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This allows both the game server and any connected clients to retrieve the map through Steam.&lt;br /&gt;
&lt;br /&gt;
You can use that form in any place that accepts maps, such as the &amp;lt;tt&amp;gt;map&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;changelevel&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;nextlevel&amp;lt;/tt&amp;gt; commands as well as the mapcycle file.  SourceMod itself has support to translate the names to their display forms and will do so in first-party plugins; third-party plugins may or may not support this functionality.&lt;br /&gt;
&lt;br /&gt;
Disregard any suggestions to subscribe to the map and copy the file to your game / fast download servers.  That is often repeated, yet bad advice.&lt;br /&gt;
&lt;br /&gt;
=== Games that aren't ===&lt;br /&gt;
&lt;br /&gt;
Non-exhaustive list of Source Engine class-based shooters with a cartoon-like visual style based on the art of Dean Cornwell, J. C. Leyendecker, and Norman Rockwell, that aren't [https://store.steampowered.com/app/440/Team_Fortress_2/ Team Fortress 2]:&lt;br /&gt;
&lt;br /&gt;
* Team Fortress 2 Classic&lt;br /&gt;
* Open Fortress&lt;br /&gt;
&lt;br /&gt;
If you're developing plugins and asking questions about one of those games, please specifically name them.  These games are not guaranteed to behave the same as &amp;quot;retail&amp;quot; Team Fortress 2, and solutions that work for retail aren't guaranteed to work on third-party mods.&lt;br /&gt;
&lt;br /&gt;
== Counter-Strike: Global Offensive ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Dedicated_Servers#Advanced_Configuration Advanced Configuration] section on the Valve Developer Wiki describes server configuration unique to CS:GO. It's different from most other mods.&lt;br /&gt;
&lt;br /&gt;
=== Responsive server console when hibernating ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;sv_hibernate_ms&amp;lt;/code&amp;gt; to 0 to make the server console more responsive when no players are online.&lt;br /&gt;
&lt;br /&gt;
== Left 4 Dead 2 ==&lt;br /&gt;
&lt;br /&gt;
=== Disabling lobby system ===&lt;br /&gt;
&lt;br /&gt;
While developing plugins, you generally don't want players being connected through Steam's lobby system.  Add the following to &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_allow_lobby_connect_only &amp;quot;0&amp;quot;;&lt;br /&gt;
sv_password &amp;quot;password_to_connect_with&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Virtual Server Configuration =&lt;br /&gt;
&lt;br /&gt;
As a developer, you may need to test on multiple platforms. To avoid having another physical machine to work on, you can use virtualization to run an operating system on your desktop.&lt;br /&gt;
&lt;br /&gt;
== Virtualbox ==&lt;br /&gt;
&lt;br /&gt;
=== Networking ===&lt;br /&gt;
&lt;br /&gt;
==== Network Address Translation ====&lt;br /&gt;
&lt;br /&gt;
With NAT plus port forwarding, the minimum would be to forward UDP from one of the host's loopback IP addresses to the server port on the VM's address.  Forwarding TCP isn't necessary unless you are interested in using the RCON protocol.&lt;br /&gt;
&lt;br /&gt;
For example, given a virtual machine with an IP address of &amp;lt;tt&amp;gt;10.0.2.15&amp;lt;/tt&amp;gt; and the server listening on port 27015, you should configure NAT as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt; (host) &amp;amp;rarr; &amp;lt;tt&amp;gt;10.0.2.15:27015&amp;lt;/tt&amp;gt; (guest)&lt;br /&gt;
&lt;br /&gt;
You can then connect to the server from the host OS by connecting to &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Any loopback IP address on the host portion is acceptable to use (that is, any address starting with &amp;lt;tt&amp;gt;127.*.*.*&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Host-Only Adapter ====&lt;br /&gt;
&lt;br /&gt;
Enable the Host-Only Adapter on your VM and statically assign the address to be in the same network as your host operating system's adapter. This allows you to connect to the server without any additional networking complexities.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide&amp;diff=11443</id>
		<title>User:Nosoop/Guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide&amp;diff=11443"/>
		<updated>2023-07-15T05:14:59Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Introduction */ Fix heading level&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= About =&lt;br /&gt;
&lt;br /&gt;
This was born out of a desire to create a detailed, yet approachable step-by-step on how to get started in SourceMod.&lt;br /&gt;
&lt;br /&gt;
= Pages =&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
* [[/Setup/]] provides a step-by-step on installing a Source Engine dedicated server, Metamod:Source, and SourceMod.&lt;br /&gt;
&lt;br /&gt;
== SourceMod ==&lt;br /&gt;
&lt;br /&gt;
* [[/Basics/]] is a walkthrough on writing one's first plugins.&lt;br /&gt;
* [[/How to X/]] is a reference page on performing common operations in SourcePawn.&lt;br /&gt;
* [[/Advanced/]] is a page with information on advanced operations (finding and calling game functions, looking up addresses, etc.).&lt;br /&gt;
* [[/Development Environments/]] has a list of common editors and instructions on configuring them to compile plugins.&lt;br /&gt;
&lt;br /&gt;
== Non-SourceMod ==&lt;br /&gt;
&lt;br /&gt;
* [[/Game Server Configuration/]] has info on configuring a server.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide&amp;diff=11442</id>
		<title>User:Nosoop/Guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide&amp;diff=11442"/>
		<updated>2023-07-15T05:13:46Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Pages */ Categorize by section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= About =&lt;br /&gt;
&lt;br /&gt;
This was born out of a desire to create a detailed, yet approachable step-by-step on how to get started in SourceMod.&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
&lt;br /&gt;
* [[/Setup/]] provides a step-by-step on installing a Source Engine dedicated server, Metamod:Source, and SourceMod.&lt;br /&gt;
&lt;br /&gt;
== SourceMod ==&lt;br /&gt;
&lt;br /&gt;
* [[/Basics/]] is a walkthrough on writing one's first plugins.&lt;br /&gt;
* [[/How to X/]] is a reference page on performing common operations.&lt;br /&gt;
* [[/Advanced/]] is a page with information on advanced operations (finding and calling game functions, looking up addresses, etc.).&lt;br /&gt;
* [[/Development Environments/]] has a list of common editors and instructions on configuring them to compile plugins.&lt;br /&gt;
&lt;br /&gt;
== Non-SourceMod ==&lt;br /&gt;
&lt;br /&gt;
* [[/Game Server Configuration/]] has info on configuring a server.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11439</id>
		<title>User:Nosoop/Guide/Advanced</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11439"/>
		<updated>2023-06-01T08:30:42Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* SDKCall Order */ Add missing variable in example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section is provided for users that want or need to work with game-specific functionality that SourceMod doesn't provide access to out of the box.&lt;br /&gt;
&lt;br /&gt;
It's assumed that you're comfortable with programming and various terms.  By the end of this page you'll have some knowledge of calling / hooking arbitrary functions in the game.&lt;br /&gt;
&lt;br /&gt;
= What is gamedata? =&lt;br /&gt;
&lt;br /&gt;
''Gamedata'', also known as game data, gameconfig, and gameconf, are files used to specify information tied to a specific game.&lt;br /&gt;
&lt;br /&gt;
As the games that SourceMod runs on are updated independently of SourceMod itself, gamedata is used as a unified way to keep plugins and extensions up to date on game changes without needing to recompile them.&lt;br /&gt;
&lt;br /&gt;
= Finding Functions =&lt;br /&gt;
&lt;br /&gt;
* TODO refer to public SDK if you don't know what you're looking for&lt;br /&gt;
* TODO explain what to do in a game with symbols&lt;br /&gt;
* TODO suggest opening IDA's options and enabling opcode bytes&lt;br /&gt;
* TODO inlined functions&lt;br /&gt;
* TODO debugging&lt;br /&gt;
&lt;br /&gt;
= Finding VTable Offsets =&lt;br /&gt;
&lt;br /&gt;
In C++, a ''virtual method table'' (shorthand &amp;amp;quot;vtable&amp;amp;quot;) is effectively an array of function pointers. It's intended for inheritance — a virtual &amp;lt;code&amp;gt;::DoThing()&amp;lt;/code&amp;gt; method can be different for different classes, and so the code will look up the correct function for a specific instance based on the table for the instance's class. Every class that uses a vtable will hold a reference to it as one of its properties.&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
Once you have the virtual call, jump to its reference in &amp;lt;tt&amp;gt;.rodata&amp;lt;/tt&amp;gt; and make a note of that address.  Scroll up until you see an offset reference (&amp;lt;tt&amp;gt;off_*&amp;lt;/tt&amp;gt; in IDA, &amp;lt;tt&amp;gt;PTR_*&amp;lt;/tt&amp;gt; in Ghidra); that is likely the first entry in the vtable (index 0).  This reference is created by disassemblers as this is the address that is stored in class instances.&lt;br /&gt;
&lt;br /&gt;
Get the difference between your virtual call's address and that of the first entry, then divide by the pointer size (4 on 32-bit platforms, 8 on 64-bit).&lt;br /&gt;
&lt;br /&gt;
For example, given a 32-bit function pointer located at &amp;lt;tt&amp;gt;011AE84Ch&amp;lt;/tt&amp;gt; and the start at &amp;lt;tt&amp;gt;011AE3C8h&amp;lt;/tt&amp;gt;, you do &amp;lt;tt&amp;gt;(0x011AE84C-0x011AE3C8) / 4&amp;lt;/tt&amp;gt;, resulting in the index 289.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if you're familiar with the code or have sources to cross-reference against, you can search for the virtual call itself.  In a Linux disassembly, it will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; get the first vtable by dereferencing the pointer at the start of the class instance&lt;br /&gt;
8B 03       mov  eax, [ebx]&lt;br /&gt;
&lt;br /&gt;
; push the class instance as a parameter&lt;br /&gt;
89 1C 24    mov  [esp], ebx&lt;br /&gt;
&lt;br /&gt;
; call the fourth entry (at index 3) in the vtable: 0xC / sizeof(void*) = 0x3&lt;br /&gt;
FF 50 0C    call dword ptr [eax+0Ch]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If the game isn't stripped of debugging symbols, use [https://asherkin.github.io/vtable/ asherkin's VTable Dumper].  It provides correct offsets for Linux binaries (as it's what it works with), and estimates usually correct offsets for Windows.&lt;br /&gt;
&lt;br /&gt;
There are instances where the dumper isn't correct, so you may need to be careful in those cases.  Known cases include:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/asherkin/vtable/issues/7 Classes that have discontinuous overloaded functions]&lt;br /&gt;
* Possibly multiple inheritance&lt;br /&gt;
&lt;br /&gt;
Aside - the layout of vtables is not the same across platforms.  Notable differences are:&lt;br /&gt;
&lt;br /&gt;
# Linux may have multiple virtual destructors; Windows appears to only have up to one.&lt;br /&gt;
# Linux overloads are in the same order as they are initially defined in the original code.  On Windows, this is the same, except that overloaded functions (those with the same name that accept different parameters) are grouped together and emitted in reverse order.&lt;br /&gt;
&lt;br /&gt;
= Creating Signatures =&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
After you've found a function, you need to tell SourceMod the sequence of bytes unique to it. Those bytes make up a ''signature''.&lt;br /&gt;
&lt;br /&gt;
{{Note|If you're using IDA and only see the mnemonics in the &amp;quot;IDA View&amp;quot; tab, make sure to set the number of opcode bytes in IDA options to a non-zero number.  8 is sufficient in most cases.}}&lt;br /&gt;
&lt;br /&gt;
You could treat just the sequence bytes as the signature directly, but this would break very easily whenever the game is updated. At the machine-code level, the ''instructions'' might be the same for &amp;amp;quot;move X to Y&amp;amp;quot;, but the ''data'' might change — X and Y might be in a different location in the binary altogether. For an example within a longer signature:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; sets esp to the offset aString&lt;br /&gt;
; the bytes 3B B3 25 01 are the absolute offset of aString in this binary in little-endian format (0x0125B33B)&lt;br /&gt;
C7 04 24 3B B3 25 01    mov     dword ptr [esp], offset aString&lt;br /&gt;
&lt;br /&gt;
; call function, the four bytes after E8 are the location of the function&lt;br /&gt;
E8 78 F0 48 00          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
&lt;br /&gt;
; sets eax to arg 0&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The naive signature for that would be &amp;lt;code&amp;gt;\xC7\x04\x24\x3B\xB3\x25\x01\xE8\x78\xF0\x48\x00\x8B\x45\x08&amp;lt;/code&amp;gt;. However, you can't rely on those bytes mentioned to be constant at all:&lt;br /&gt;
&lt;br /&gt;
* The offsets of &amp;lt;code&amp;gt;aString&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UTIL_VarArgs&amp;lt;/code&amp;gt; might be located somewhere else after a game update&lt;br /&gt;
* Relocations may be performed such that the data bytes are different in memory from its on-disk representation&lt;br /&gt;
&lt;br /&gt;
As a solution to this, you use wildcards to mask off the bytes you don't care about. For SourceMod game config files, the sequence &amp;lt;code&amp;gt;\x2A&amp;lt;/code&amp;gt; indicates that particular byte shouldn't be checked and to continue to the next one.&lt;br /&gt;
&lt;br /&gt;
Here is what the previous signature looks like with the masked bytes displayed as &amp;lt;code&amp;gt;??&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
C7 04 24 ?? ?? ?? ??    mov     dword ptr [esp], offset aString&lt;br /&gt;
E8 ?? ?? ?? ??          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A masked signature would then be &amp;lt;code&amp;gt;\xC7\x04\x24\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x45\x08&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Masking is used mainly for offsets, such as for functions and variables. Instructions generally don't change unless the function code itself is modified, at which point you'll want to revisit your binary and update accordingly.&lt;br /&gt;
&lt;br /&gt;
If you're using DHooks with byte signatures (covered later), you may want to also mask out the first six bytes, as a detour will patch in an unconditional JMP at the start to trampoline into a user-defined function, and subsequent scans for the byte signature will fail.&lt;br /&gt;
&lt;br /&gt;
{{Note|This is no longer the case as of SourceMod 1.11, which stores a copy of the original data for scanning purposes.  However, it's noted here for historical / implementation detail reasons.}}&lt;br /&gt;
&lt;br /&gt;
For an extended lesson, you can look at the following material:&lt;br /&gt;
&lt;br /&gt;
* [https://wiki.alliedmods.net/Signature_Scanning Signature Scanning] on the AlliedModders wiki&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If you're using IDA (including Free), use the [https://github.com/alliedmodders/sourcemod/blob/master/tools/ida_scripts/makesig7.idc &amp;lt;code&amp;gt;makesig7.idc&amp;lt;/code&amp;gt;] script. If you're using Ghidra, use [https://github.com/alliedmodders/sourcemod/blob/master/tools/ghidra_scripts/makesig.py &amp;lt;code&amp;gt;makesig.py&amp;lt;/code&amp;gt;].&lt;br /&gt;
&lt;br /&gt;
They generally do pretty well at finding and masking byte signatures, but when it fails or you want a more robust signature, you should understand how to create the signatures manually.&lt;br /&gt;
&lt;br /&gt;
Both scripts may produce different byte signatures for the same function due to using different methods to determine if a given byte should be masked.&lt;br /&gt;
&lt;br /&gt;
It's exceedingly rare, but possible that the binary has two copies of the exact same short function (for example, when they are typechecked and statically casted to different subclasses). Both scripts will fail in that case. SourceMod's signature scanner will use the first match it finds, so if any match is acceptable, you can still use an appropriately masked signature.&lt;br /&gt;
&lt;br /&gt;
If two copies of a function seem to exist, be sure to look at the disassembly to make sure that the functions are indeed the same.&lt;br /&gt;
&lt;br /&gt;
= Finding Addresses =&lt;br /&gt;
&lt;br /&gt;
Sometimes you have a symbol, but you need an address to work with.  That is what the &amp;quot;Addresses&amp;quot; section of a game configuration file is used for.&lt;br /&gt;
&lt;br /&gt;
To find an address, you start from a known location reference (signature).  You may then have to jump to references (that is, dereference locations), then get an offset from the previous reference.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; keys indicate an offset to load / dereference relative to the previous address, and &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; means to shift the previous address without any dereference.  These key / value pairs are processed in the order you specify them in the file; &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; is only valid as the last &amp;quot;operation&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For a C++-like example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// start from an address&lt;br /&gt;
// &amp;quot;FindLocation&amp;quot; would return the location of either a named symbol reference or the start of a byte signature&lt;br /&gt;
uintptr_t addr = FindLocation(&amp;quot;some_signature&amp;quot;);&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr + 40); // gameconf: &amp;quot;read&amp;quot; &amp;quot;40&amp;quot;&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr); // gameconf: &amp;quot;read&amp;quot; &amp;quot;0&amp;quot;&lt;br /&gt;
addr += 13; // gameconf: &amp;quot;offset&amp;quot; &amp;quot;13&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Calling Game Functions =&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== SDKCall Order ==&lt;br /&gt;
&lt;br /&gt;
When performing an {{SourceMod API|file=sdktools|function=SDKCall}}, the parameters need to be passed in the following order:&lt;br /&gt;
&lt;br /&gt;
# The SDKCall handle received from {{SourceMod API|file=sdktools|function=EndPrepSDKCall}}.&lt;br /&gt;
# The &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; instance.  &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; may be omitted in the following cases:&lt;br /&gt;
#* The function was declared as static, where there is no &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; to pass in.&lt;br /&gt;
#* The function was declared with the &amp;lt;tt&amp;gt;SDKCall_GameRules&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SDKCall_EntityList&amp;lt;/tt&amp;gt; call types; SDKTools itself will provide the appropriate global instance.&lt;br /&gt;
# The return buffer, if applicable.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;Vector&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;QAngle&amp;lt;/tt&amp;gt;, the parameter is a &amp;lt;tt&amp;gt;float[3]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt;, the parameters should be a &amp;lt;tt&amp;gt;char[]&amp;lt;/tt&amp;gt; buffer and an &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; specifying the size of the buffer.  The return value of the SDKCall will be the number of characters written, or -1 if the function returned a null pointer (to differentiate between an empty string).&lt;br /&gt;
#* If the function returns a primitive type / entity / edict, it will be the return value of the SDKCall, so no such return buffer is necessary.&lt;br /&gt;
# Any remaining parameters for the function.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// Vector CBaseCombatCharacter::Weapon_ShootPosition() -- has 'this' and 'Vector' return&lt;br /&gt;
float vecShootPosition[3];&lt;br /&gt;
SDKCall(g_hSDKCall, client, vecShootPosition);&lt;br /&gt;
&lt;br /&gt;
// const char *CBaseAnimating::GetSequenceName(int iSequence) -- has 'this', 'char*' return, and parameter&lt;br /&gt;
char sequenceName[64];&lt;br /&gt;
SDKCall(g_hSDKCall, entity, sequenceName, sizeof(sequenceName), iSequence);&lt;br /&gt;
&lt;br /&gt;
// bool CGlobalEntityList::IsEntityPtr(void* pTest) -- SDKCall_EntityList is used, so no 'this' explicitly needed&lt;br /&gt;
// SDKCall passes the return value from the called function as its return value, so use an assignment operator&lt;br /&gt;
Address pTest;&lt;br /&gt;
bool result = SDKCall(g_hSDKCall, pTest);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calling via Signature or Offset? ==&lt;br /&gt;
&lt;br /&gt;
If you have a class with a virtual method, you generally should set up the &amp;lt;tt&amp;gt;SDKCall&amp;lt;/tt&amp;gt; to take a virtual offset.  Doing so allows your plugin to have the expected interactions with other plugin's hooks, covered in the next section.&lt;br /&gt;
&lt;br /&gt;
You should use a signature either when the function is not virtual or if you need to bypass the virtual override on an entity (e.g. calling the parent class's function).  In those instances, only detours will take effect.&lt;br /&gt;
&lt;br /&gt;
= Hooking Game Functions (with DHooks) =&lt;br /&gt;
&lt;br /&gt;
DHooks is an extension bundled with SourceMod that enables plugins to hook functions of their choosing (currently restricted to those accessible via server / engine binaries).  You may use its functionality by including {{SourceMod API|file=dhooks}}.&lt;br /&gt;
&lt;br /&gt;
As with {{SourceMod API|file=sdktools|function=SDKCall}}s, you must ensure that your hook setup is declared with the same parameter and return types to ensure the server continues to operate as you'd expect.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== Virtual Hook or Detour? ==&lt;br /&gt;
&lt;br /&gt;
A virtual hook is mainly used for hooking virtual methods of a class; a detour is used for hooking any function.&lt;br /&gt;
&lt;br /&gt;
While detours can be used to hook the function a virtual table calls into, virtual hooks still have the merit of hooking specific classes / instances.  More specifically:&lt;br /&gt;
&lt;br /&gt;
* DHooks provides the bookkeeping on which instances are and aren't hooked, so for virtual hooks the callback will only be invoked on those you specifically hook.  On detours, you have to filter on instances yourself.&lt;br /&gt;
* On chained inheritance, a virtual hook will only act on the exact class and not any parent nor subclasses, even if they all point to the same virtual function.  Detours will, again, be called on any invocation of the function, including calls to it made by its subclass.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11438</id>
		<title>User:Nosoop/Guide/Advanced</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11438"/>
		<updated>2023-06-01T08:28:05Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Calling Game Functions */ Add section on whether to set up function calls using signatures or offsets&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section is provided for users that want or need to work with game-specific functionality that SourceMod doesn't provide access to out of the box.&lt;br /&gt;
&lt;br /&gt;
It's assumed that you're comfortable with programming and various terms.  By the end of this page you'll have some knowledge of calling / hooking arbitrary functions in the game.&lt;br /&gt;
&lt;br /&gt;
= What is gamedata? =&lt;br /&gt;
&lt;br /&gt;
''Gamedata'', also known as game data, gameconfig, and gameconf, are files used to specify information tied to a specific game.&lt;br /&gt;
&lt;br /&gt;
As the games that SourceMod runs on are updated independently of SourceMod itself, gamedata is used as a unified way to keep plugins and extensions up to date on game changes without needing to recompile them.&lt;br /&gt;
&lt;br /&gt;
= Finding Functions =&lt;br /&gt;
&lt;br /&gt;
* TODO refer to public SDK if you don't know what you're looking for&lt;br /&gt;
* TODO explain what to do in a game with symbols&lt;br /&gt;
* TODO suggest opening IDA's options and enabling opcode bytes&lt;br /&gt;
* TODO inlined functions&lt;br /&gt;
* TODO debugging&lt;br /&gt;
&lt;br /&gt;
= Finding VTable Offsets =&lt;br /&gt;
&lt;br /&gt;
In C++, a ''virtual method table'' (shorthand &amp;amp;quot;vtable&amp;amp;quot;) is effectively an array of function pointers. It's intended for inheritance — a virtual &amp;lt;code&amp;gt;::DoThing()&amp;lt;/code&amp;gt; method can be different for different classes, and so the code will look up the correct function for a specific instance based on the table for the instance's class. Every class that uses a vtable will hold a reference to it as one of its properties.&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
Once you have the virtual call, jump to its reference in &amp;lt;tt&amp;gt;.rodata&amp;lt;/tt&amp;gt; and make a note of that address.  Scroll up until you see an offset reference (&amp;lt;tt&amp;gt;off_*&amp;lt;/tt&amp;gt; in IDA, &amp;lt;tt&amp;gt;PTR_*&amp;lt;/tt&amp;gt; in Ghidra); that is likely the first entry in the vtable (index 0).  This reference is created by disassemblers as this is the address that is stored in class instances.&lt;br /&gt;
&lt;br /&gt;
Get the difference between your virtual call's address and that of the first entry, then divide by the pointer size (4 on 32-bit platforms, 8 on 64-bit).&lt;br /&gt;
&lt;br /&gt;
For example, given a 32-bit function pointer located at &amp;lt;tt&amp;gt;011AE84Ch&amp;lt;/tt&amp;gt; and the start at &amp;lt;tt&amp;gt;011AE3C8h&amp;lt;/tt&amp;gt;, you do &amp;lt;tt&amp;gt;(0x011AE84C-0x011AE3C8) / 4&amp;lt;/tt&amp;gt;, resulting in the index 289.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if you're familiar with the code or have sources to cross-reference against, you can search for the virtual call itself.  In a Linux disassembly, it will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; get the first vtable by dereferencing the pointer at the start of the class instance&lt;br /&gt;
8B 03       mov  eax, [ebx]&lt;br /&gt;
&lt;br /&gt;
; push the class instance as a parameter&lt;br /&gt;
89 1C 24    mov  [esp], ebx&lt;br /&gt;
&lt;br /&gt;
; call the fourth entry (at index 3) in the vtable: 0xC / sizeof(void*) = 0x3&lt;br /&gt;
FF 50 0C    call dword ptr [eax+0Ch]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If the game isn't stripped of debugging symbols, use [https://asherkin.github.io/vtable/ asherkin's VTable Dumper].  It provides correct offsets for Linux binaries (as it's what it works with), and estimates usually correct offsets for Windows.&lt;br /&gt;
&lt;br /&gt;
There are instances where the dumper isn't correct, so you may need to be careful in those cases.  Known cases include:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/asherkin/vtable/issues/7 Classes that have discontinuous overloaded functions]&lt;br /&gt;
* Possibly multiple inheritance&lt;br /&gt;
&lt;br /&gt;
Aside - the layout of vtables is not the same across platforms.  Notable differences are:&lt;br /&gt;
&lt;br /&gt;
# Linux may have multiple virtual destructors; Windows appears to only have up to one.&lt;br /&gt;
# Linux overloads are in the same order as they are initially defined in the original code.  On Windows, this is the same, except that overloaded functions (those with the same name that accept different parameters) are grouped together and emitted in reverse order.&lt;br /&gt;
&lt;br /&gt;
= Creating Signatures =&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
After you've found a function, you need to tell SourceMod the sequence of bytes unique to it. Those bytes make up a ''signature''.&lt;br /&gt;
&lt;br /&gt;
{{Note|If you're using IDA and only see the mnemonics in the &amp;quot;IDA View&amp;quot; tab, make sure to set the number of opcode bytes in IDA options to a non-zero number.  8 is sufficient in most cases.}}&lt;br /&gt;
&lt;br /&gt;
You could treat just the sequence bytes as the signature directly, but this would break very easily whenever the game is updated. At the machine-code level, the ''instructions'' might be the same for &amp;amp;quot;move X to Y&amp;amp;quot;, but the ''data'' might change — X and Y might be in a different location in the binary altogether. For an example within a longer signature:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; sets esp to the offset aString&lt;br /&gt;
; the bytes 3B B3 25 01 are the absolute offset of aString in this binary in little-endian format (0x0125B33B)&lt;br /&gt;
C7 04 24 3B B3 25 01    mov     dword ptr [esp], offset aString&lt;br /&gt;
&lt;br /&gt;
; call function, the four bytes after E8 are the location of the function&lt;br /&gt;
E8 78 F0 48 00          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
&lt;br /&gt;
; sets eax to arg 0&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The naive signature for that would be &amp;lt;code&amp;gt;\xC7\x04\x24\x3B\xB3\x25\x01\xE8\x78\xF0\x48\x00\x8B\x45\x08&amp;lt;/code&amp;gt;. However, you can't rely on those bytes mentioned to be constant at all:&lt;br /&gt;
&lt;br /&gt;
* The offsets of &amp;lt;code&amp;gt;aString&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UTIL_VarArgs&amp;lt;/code&amp;gt; might be located somewhere else after a game update&lt;br /&gt;
* Relocations may be performed such that the data bytes are different in memory from its on-disk representation&lt;br /&gt;
&lt;br /&gt;
As a solution to this, you use wildcards to mask off the bytes you don't care about. For SourceMod game config files, the sequence &amp;lt;code&amp;gt;\x2A&amp;lt;/code&amp;gt; indicates that particular byte shouldn't be checked and to continue to the next one.&lt;br /&gt;
&lt;br /&gt;
Here is what the previous signature looks like with the masked bytes displayed as &amp;lt;code&amp;gt;??&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
C7 04 24 ?? ?? ?? ??    mov     dword ptr [esp], offset aString&lt;br /&gt;
E8 ?? ?? ?? ??          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A masked signature would then be &amp;lt;code&amp;gt;\xC7\x04\x24\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x45\x08&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Masking is used mainly for offsets, such as for functions and variables. Instructions generally don't change unless the function code itself is modified, at which point you'll want to revisit your binary and update accordingly.&lt;br /&gt;
&lt;br /&gt;
If you're using DHooks with byte signatures (covered later), you may want to also mask out the first six bytes, as a detour will patch in an unconditional JMP at the start to trampoline into a user-defined function, and subsequent scans for the byte signature will fail.&lt;br /&gt;
&lt;br /&gt;
{{Note|This is no longer the case as of SourceMod 1.11, which stores a copy of the original data for scanning purposes.  However, it's noted here for historical / implementation detail reasons.}}&lt;br /&gt;
&lt;br /&gt;
For an extended lesson, you can look at the following material:&lt;br /&gt;
&lt;br /&gt;
* [https://wiki.alliedmods.net/Signature_Scanning Signature Scanning] on the AlliedModders wiki&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If you're using IDA (including Free), use the [https://github.com/alliedmodders/sourcemod/blob/master/tools/ida_scripts/makesig7.idc &amp;lt;code&amp;gt;makesig7.idc&amp;lt;/code&amp;gt;] script. If you're using Ghidra, use [https://github.com/alliedmodders/sourcemod/blob/master/tools/ghidra_scripts/makesig.py &amp;lt;code&amp;gt;makesig.py&amp;lt;/code&amp;gt;].&lt;br /&gt;
&lt;br /&gt;
They generally do pretty well at finding and masking byte signatures, but when it fails or you want a more robust signature, you should understand how to create the signatures manually.&lt;br /&gt;
&lt;br /&gt;
Both scripts may produce different byte signatures for the same function due to using different methods to determine if a given byte should be masked.&lt;br /&gt;
&lt;br /&gt;
It's exceedingly rare, but possible that the binary has two copies of the exact same short function (for example, when they are typechecked and statically casted to different subclasses). Both scripts will fail in that case. SourceMod's signature scanner will use the first match it finds, so if any match is acceptable, you can still use an appropriately masked signature.&lt;br /&gt;
&lt;br /&gt;
If two copies of a function seem to exist, be sure to look at the disassembly to make sure that the functions are indeed the same.&lt;br /&gt;
&lt;br /&gt;
= Finding Addresses =&lt;br /&gt;
&lt;br /&gt;
Sometimes you have a symbol, but you need an address to work with.  That is what the &amp;quot;Addresses&amp;quot; section of a game configuration file is used for.&lt;br /&gt;
&lt;br /&gt;
To find an address, you start from a known location reference (signature).  You may then have to jump to references (that is, dereference locations), then get an offset from the previous reference.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; keys indicate an offset to load / dereference relative to the previous address, and &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; means to shift the previous address without any dereference.  These key / value pairs are processed in the order you specify them in the file; &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; is only valid as the last &amp;quot;operation&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For a C++-like example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// start from an address&lt;br /&gt;
// &amp;quot;FindLocation&amp;quot; would return the location of either a named symbol reference or the start of a byte signature&lt;br /&gt;
uintptr_t addr = FindLocation(&amp;quot;some_signature&amp;quot;);&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr + 40); // gameconf: &amp;quot;read&amp;quot; &amp;quot;40&amp;quot;&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr); // gameconf: &amp;quot;read&amp;quot; &amp;quot;0&amp;quot;&lt;br /&gt;
addr += 13; // gameconf: &amp;quot;offset&amp;quot; &amp;quot;13&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Calling Game Functions =&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== SDKCall Order ==&lt;br /&gt;
&lt;br /&gt;
When performing an {{SourceMod API|file=sdktools|function=SDKCall}}, the parameters need to be passed in the following order:&lt;br /&gt;
&lt;br /&gt;
# The SDKCall handle received from {{SourceMod API|file=sdktools|function=EndPrepSDKCall}}.&lt;br /&gt;
# The &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; instance.  &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; may be omitted in the following cases:&lt;br /&gt;
#* The function was declared as static, where there is no &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; to pass in.&lt;br /&gt;
#* The function was declared with the &amp;lt;tt&amp;gt;SDKCall_GameRules&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SDKCall_EntityList&amp;lt;/tt&amp;gt; call types; SDKTools itself will provide the appropriate global instance.&lt;br /&gt;
# The return buffer, if applicable.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;Vector&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;QAngle&amp;lt;/tt&amp;gt;, the parameter is a &amp;lt;tt&amp;gt;float[3]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt;, the parameters should be a &amp;lt;tt&amp;gt;char[]&amp;lt;/tt&amp;gt; buffer and an &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; specifying the size of the buffer.  The return value of the SDKCall will be the number of characters written, or -1 if the function returned a null pointer (to differentiate between an empty string).&lt;br /&gt;
#* If the function returns a primitive type / entity / edict, it will be the return value of the SDKCall, so no such return buffer is necessary.&lt;br /&gt;
# Any remaining parameters for the function.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// Vector CBaseCombatCharacter::Weapon_ShootPosition() -- has 'this' and 'Vector' return&lt;br /&gt;
float vecShootPosition[3];&lt;br /&gt;
SDKCall(g_hSDKCall, client, vecShootPosition);&lt;br /&gt;
&lt;br /&gt;
// const char *CBaseAnimating::GetSequenceName(int iSequence) -- has 'this', 'char*' return, and parameter&lt;br /&gt;
char sequenceName[64];&lt;br /&gt;
SDKCall(g_hSDKCall, entity, sequenceName, sizeof(sequenceName), iSequence);&lt;br /&gt;
&lt;br /&gt;
// bool CGlobalEntityList::IsEntityPtr(void* pTest) -- SDKCall_EntityList is used, so no 'this' explicitly needed&lt;br /&gt;
// SDKCall passes the return value from the called function as its return value, so use an assignment operator&lt;br /&gt;
bool result = SDKCall(g_hSDKCall, pTest);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Calling via Signature or Offset? ==&lt;br /&gt;
&lt;br /&gt;
If you have a class with a virtual method, you generally should set up the &amp;lt;tt&amp;gt;SDKCall&amp;lt;/tt&amp;gt; to take a virtual offset.  Doing so allows your plugin to have the expected interactions with other plugin's hooks, covered in the next section.&lt;br /&gt;
&lt;br /&gt;
You should use a signature either when the function is not virtual or if you need to bypass the virtual override on an entity (e.g. calling the parent class's function).  In those instances, only detours will take effect.&lt;br /&gt;
&lt;br /&gt;
= Hooking Game Functions (with DHooks) =&lt;br /&gt;
&lt;br /&gt;
DHooks is an extension bundled with SourceMod that enables plugins to hook functions of their choosing (currently restricted to those accessible via server / engine binaries).  You may use its functionality by including {{SourceMod API|file=dhooks}}.&lt;br /&gt;
&lt;br /&gt;
As with {{SourceMod API|file=sdktools|function=SDKCall}}s, you must ensure that your hook setup is declared with the same parameter and return types to ensure the server continues to operate as you'd expect.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== Virtual Hook or Detour? ==&lt;br /&gt;
&lt;br /&gt;
A virtual hook is mainly used for hooking virtual methods of a class; a detour is used for hooking any function.&lt;br /&gt;
&lt;br /&gt;
While detours can be used to hook the function a virtual table calls into, virtual hooks still have the merit of hooking specific classes / instances.  More specifically:&lt;br /&gt;
&lt;br /&gt;
* DHooks provides the bookkeeping on which instances are and aren't hooked, so for virtual hooks the callback will only be invoked on those you specifically hook.  On detours, you have to filter on instances yourself.&lt;br /&gt;
* On chained inheritance, a virtual hook will only act on the exact class and not any parent nor subclasses, even if they all point to the same virtual function.  Detours will, again, be called on any invocation of the function, including calls to it made by its subclass.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11437</id>
		<title>User:Nosoop/Guide/Game Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11437"/>
		<updated>2023-05-26T11:05:22Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* 64-bit Linux systems and 32-bit executables */ Add zlib&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine games often differ in configuration; here are some basic suggestions on how to set them up for either testing or production use.&lt;br /&gt;
&lt;br /&gt;
= General =&lt;br /&gt;
&lt;br /&gt;
The following section(s) apply to most, if not all games.&lt;br /&gt;
&lt;br /&gt;
== Fast Downloads ==&lt;br /&gt;
&lt;br /&gt;
The Source Engine normally provides downloads over the same channel as gameplay, which is rather slow.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;quot;Fast&amp;amp;quot; downloads are downloads served out-of-band over HTTP, and as such you will need to have a web (HTTP) server up and running to take advantage of this functionality.  This is highly recommended if you are running a server with any amount of custom content that a player needs to download (models, sounds, maps).&lt;br /&gt;
&lt;br /&gt;
If you're using a game server provider, you may already have access to a web server for fast download purposes; check with your provider to confirm.&lt;br /&gt;
&lt;br /&gt;
Examples of web servers include: [https://www.nginx.com/ nginx], [https://caddyserver.com/ Caddy], [https://httpd.apache.org/ Apache], [https://www.rejetto.com/hfs/ HFS], and [https://en.wikipedia.org/wiki/Comparison_of_web_server_software many others] (and many more not included in that list).&lt;br /&gt;
&lt;br /&gt;
Once you have an HTTP server running, configure &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_downloadurl &amp;amp;quot;http://{your_server_location}/{path}&amp;amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The URL must be quoted, as &amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; is treated as the start of a comment and if left unquoted, the rest of the line will be ignored.  Do not include a trailing slash &amp;amp;mdash; the game client adds one when making the request; web servers are not guaranteed to collapse double slashes in the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;{path}&amp;lt;/tt&amp;gt; should be the path on your server that would translate to the root of your game server.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a file &amp;lt;tt&amp;gt;sound/my_server/fart.mp3&amp;lt;/tt&amp;gt; and an &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;, the client will request &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads/sound/my_server/fart.mp3&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; (and its BZip2-compressed equivalent).&lt;br /&gt;
&lt;br /&gt;
You will need to also copy the files from the game server to the web server.&lt;br /&gt;
&lt;br /&gt;
== SourceMod extension not loading ==&lt;br /&gt;
&lt;br /&gt;
By default, if no plugin depends on an extension, it won't be loaded automatically, nor will it show up in &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;sm exts load ${extension}&amp;lt;/tt&amp;gt; if you'd like to test if it loads and to see if it fails, or add an &amp;lt;tt&amp;gt;${extension}.autoload&amp;lt;/tt&amp;gt; file (empty or not) in the extensions directory if you always want it to load.&lt;br /&gt;
&lt;br /&gt;
== RCON ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Source_RCON_Protocol Source RCON Protocol] allows users to remotely issue console commands to dedicated server instances.&lt;br /&gt;
&lt;br /&gt;
You likely won't need this, because you can issue console commands through&lt;br /&gt;
&lt;br /&gt;
* running the server instance in a terminal multiplexer session (with &amp;lt;tt&amp;gt;screen&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;tmux&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* your game server provider providing a web interface that provides real-time console input and output&lt;br /&gt;
&lt;br /&gt;
If you have full access to the machine that your server runs on, you can block RCON packets by dropping TCP packets going to the game port entirely.&lt;br /&gt;
&lt;br /&gt;
Note that doing so will also prevent use of third-party extensions that process TCP connections on the game port, such as [https://forums.alliedmods.net/showthread.php?t=270962 Conplex].&lt;br /&gt;
&lt;br /&gt;
You can use the following on Linux, if you are using iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# the following commands append rules to the firewall; the order here is important&lt;br /&gt;
# change 27015 to the game port&lt;br /&gt;
&lt;br /&gt;
# accept RCON traffic that comes from the same machine, for things like SourceBans&lt;br /&gt;
# if you know you aren't using anything else that relies on RCON you may omit this&lt;br /&gt;
# if legitimate RCON traffic may come from elsewhere, change the source network (-s 127.0.0.1/8),&lt;br /&gt;
# or append additional rules for addresses that should be allowed&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -s 127.0.0.1/8 -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
# drop everything else going to the game port&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Platform-specific =&lt;br /&gt;
&lt;br /&gt;
== Linux extension failing to load on outdated &amp;lt;tt&amp;gt;GLIBCXX_*&amp;lt;/tt&amp;gt; version ==&lt;br /&gt;
&lt;br /&gt;
Various Source Engine games (Counter Strike: Source, Day of Defeat: Source, Counter Strike: Global Offensive, third-party games using the Source SDK modding system, possibly others) bundle standard libraries that are older than what current operating systems ship with, but newer than those that Valve ships as a baseline.&lt;br /&gt;
&lt;br /&gt;
Software that depends on new versions of libraries will fail to load.  This includes Metamod:Source, SourceMod, and other native code / plugins / extension.&lt;br /&gt;
&lt;br /&gt;
You can choose to do one of the following:&lt;br /&gt;
&lt;br /&gt;
* Remove any existing copies of &amp;lt;tt&amp;gt;bin/libstdc++.so.6&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to your game install directory (not the root of the filesytem); this will let the game load the system libraries.&lt;br /&gt;
** If you are on a 64-bit system, continue to the [[#64-bit_Linux_systems_and_32-bit_executables|next section]] to ensure the system's 32-bit libraries are actually available after removing the Valve-bundled copies.&lt;br /&gt;
* If your operating system is also dated, you will need rebuild the extension using an older build environment, or upgrade to a newer one.  If you plan on recompiling the extension, the [https://github.com/ValveSoftware/steam-runtime Steam Runtime SDK] is considered the baseline of support.&lt;br /&gt;
&lt;br /&gt;
== 64-bit Linux systems and 32-bit executables ==&lt;br /&gt;
&lt;br /&gt;
[https://sporks.space/2022/02/27/win32-is-the-stable-linux-userland-abi-and-the-consequences/ Unlike Windows], 64-bit Linux systems are not guaranteed to ship with full compatibility for 32-bit executables by default.&lt;br /&gt;
&lt;br /&gt;
Depending on your distribution, you will need to run one of the following commands as root to install the required packages / libraries:&lt;br /&gt;
&lt;br /&gt;
* Debian / Ubuntu: &amp;lt;tt&amp;gt;apt install gcc-multilib lib32z1&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Arch: &amp;lt;tt&amp;gt;pacman -S lib32-gcc-libs lib32-zlib&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Fedora: &amp;lt;tt&amp;gt;yum -y install glibc.i686 zlib.i686&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Game Specific =&lt;br /&gt;
&lt;br /&gt;
== Team Fortress 2 ==&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.teamfortress.com/wiki/Dedicated_server_configuration Dedicated server configuration] section on the Team Fortress 2 Official Wiki provides general configuration instructions.  Depending on the platform you're working on, you may also be interested in the sections for [https://wiki.teamfortress.com/wiki/Linux_dedicated_server Linux] and [https://wiki.teamfortress.com/wiki/Windows_dedicated_server Windows].&lt;br /&gt;
&lt;br /&gt;
=== Mann vs. Machine ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;tt&amp;gt;tf_mvm_min_players_to_start&amp;lt;/tt&amp;gt; to 1 to only require one player to ready up and start the mission.&lt;br /&gt;
&lt;br /&gt;
=== Steam Datagram Relay ===&lt;br /&gt;
&lt;br /&gt;
The Steam Datagram Relay routes both server and client connections through the Steam network, hiding the IP address of each from the other.&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;tt&amp;gt;-enablefakeip&amp;lt;/tt&amp;gt; in the server's launch options to enable.  The server will then report &amp;quot;FakeIP allocation succeeded&amp;quot; at the end of startup; use that IP address / port combination in your game client to connect to the server.  This allocation will change on every server startup.&lt;br /&gt;
&lt;br /&gt;
=== Games that aren't ===&lt;br /&gt;
&lt;br /&gt;
Non-exhaustive list of Source Engine class-based shooters with a cartoon-like visual style based on the art of Dean Cornwell, J. C. Leyendecker, and Norman Rockwell, that aren't [https://store.steampowered.com/app/440/Team_Fortress_2/ Team Fortress 2]:&lt;br /&gt;
&lt;br /&gt;
* Team Fortress 2 Classic&lt;br /&gt;
* Open Fortress&lt;br /&gt;
&lt;br /&gt;
If you're developing plugins and asking questions about one of those games, please specifically name them.  These games are not guaranteed to behave the same as &amp;quot;retail&amp;quot; Team Fortress 2, and solutions that work for retail aren't guaranteed to work on third-party mods.&lt;br /&gt;
&lt;br /&gt;
== Counter-Strike: Global Offensive ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Dedicated_Servers#Advanced_Configuration Advanced Configuration] section on the Valve Developer Wiki describes server configuration unique to CS:GO. It's different from most other mods.&lt;br /&gt;
&lt;br /&gt;
=== Responsive server console when hibernating ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;sv_hibernate_ms&amp;lt;/code&amp;gt; to 0 to make the server console more responsive when no players are online.&lt;br /&gt;
&lt;br /&gt;
== Left 4 Dead 2 ==&lt;br /&gt;
&lt;br /&gt;
=== Disabling lobby system ===&lt;br /&gt;
&lt;br /&gt;
While developing plugins, you generally don't want players being connected through Steam's lobby system.  Add the following to &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_allow_lobby_connect_only &amp;quot;0&amp;quot;;&lt;br /&gt;
sv_password &amp;quot;password_to_connect_with&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Virtual Server Configuration =&lt;br /&gt;
&lt;br /&gt;
As a developer, you may need to test on multiple platforms. To avoid having another physical machine to work on, you can use virtualization to run an operating system on your desktop.&lt;br /&gt;
&lt;br /&gt;
== Virtualbox ==&lt;br /&gt;
&lt;br /&gt;
=== Networking ===&lt;br /&gt;
&lt;br /&gt;
==== Network Address Translation ====&lt;br /&gt;
&lt;br /&gt;
With NAT plus port forwarding, the minimum would be to forward UDP from one of the host's loopback IP addresses to the server port on the VM's address.  Forwarding TCP isn't necessary unless you are interested in using the RCON protocol.&lt;br /&gt;
&lt;br /&gt;
For example, given a virtual machine with an IP address of &amp;lt;tt&amp;gt;10.0.2.15&amp;lt;/tt&amp;gt; and the server listening on port 27015, you should configure NAT as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt; (host) &amp;amp;rarr; &amp;lt;tt&amp;gt;10.0.2.15:27015&amp;lt;/tt&amp;gt; (guest)&lt;br /&gt;
&lt;br /&gt;
You can then connect to the server from the host OS by connecting to &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Any loopback IP address on the host portion is acceptable to use (that is, any address starting with &amp;lt;tt&amp;gt;127.*.*.*&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Host-Only Adapter ====&lt;br /&gt;
&lt;br /&gt;
Enable the Host-Only Adapter on your VM and statically assign the address to be in the same network as your host operating system's adapter. This allows you to connect to the server without any additional networking complexities.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11436</id>
		<title>User:Nosoop/Guide/Game Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11436"/>
		<updated>2023-05-12T05:48:27Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* General */ Add section on RCON&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine games often differ in configuration; here are some basic suggestions on how to set them up for either testing or production use.&lt;br /&gt;
&lt;br /&gt;
= General =&lt;br /&gt;
&lt;br /&gt;
The following section(s) apply to most, if not all games.&lt;br /&gt;
&lt;br /&gt;
== Fast Downloads ==&lt;br /&gt;
&lt;br /&gt;
The Source Engine normally provides downloads over the same channel as gameplay, which is rather slow.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;quot;Fast&amp;amp;quot; downloads are downloads served out-of-band over HTTP, and as such you will need to have a web (HTTP) server up and running to take advantage of this functionality.  This is highly recommended if you are running a server with any amount of custom content that a player needs to download (models, sounds, maps).&lt;br /&gt;
&lt;br /&gt;
If you're using a game server provider, you may already have access to a web server for fast download purposes; check with your provider to confirm.&lt;br /&gt;
&lt;br /&gt;
Examples of web servers include: [https://www.nginx.com/ nginx], [https://caddyserver.com/ Caddy], [https://httpd.apache.org/ Apache], [https://www.rejetto.com/hfs/ HFS], and [https://en.wikipedia.org/wiki/Comparison_of_web_server_software many others] (and many more not included in that list).&lt;br /&gt;
&lt;br /&gt;
Once you have an HTTP server running, configure &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_downloadurl &amp;amp;quot;http://{your_server_location}/{path}&amp;amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The URL must be quoted, as &amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; is treated as the start of a comment and if left unquoted, the rest of the line will be ignored.  Do not include a trailing slash &amp;amp;mdash; the game client adds one when making the request; web servers are not guaranteed to collapse double slashes in the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;{path}&amp;lt;/tt&amp;gt; should be the path on your server that would translate to the root of your game server.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a file &amp;lt;tt&amp;gt;sound/my_server/fart.mp3&amp;lt;/tt&amp;gt; and an &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;, the client will request &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads/sound/my_server/fart.mp3&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; (and its BZip2-compressed equivalent).&lt;br /&gt;
&lt;br /&gt;
You will need to also copy the files from the game server to the web server.&lt;br /&gt;
&lt;br /&gt;
== SourceMod extension not loading ==&lt;br /&gt;
&lt;br /&gt;
By default, if no plugin depends on an extension, it won't be loaded automatically, nor will it show up in &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;sm exts load ${extension}&amp;lt;/tt&amp;gt; if you'd like to test if it loads and to see if it fails, or add an &amp;lt;tt&amp;gt;${extension}.autoload&amp;lt;/tt&amp;gt; file (empty or not) in the extensions directory if you always want it to load.&lt;br /&gt;
&lt;br /&gt;
== RCON ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Source_RCON_Protocol Source RCON Protocol] allows users to remotely issue console commands to dedicated server instances.&lt;br /&gt;
&lt;br /&gt;
You likely won't need this, because you can issue console commands through&lt;br /&gt;
&lt;br /&gt;
* running the server instance in a terminal multiplexer session (with &amp;lt;tt&amp;gt;screen&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;tmux&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* your game server provider providing a web interface that provides real-time console input and output&lt;br /&gt;
&lt;br /&gt;
If you have full access to the machine that your server runs on, you can block RCON packets by dropping TCP packets going to the game port entirely.&lt;br /&gt;
&lt;br /&gt;
Note that doing so will also prevent use of third-party extensions that process TCP connections on the game port, such as [https://forums.alliedmods.net/showthread.php?t=270962 Conplex].&lt;br /&gt;
&lt;br /&gt;
You can use the following on Linux, if you are using iptables:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# the following commands append rules to the firewall; the order here is important&lt;br /&gt;
# change 27015 to the game port&lt;br /&gt;
&lt;br /&gt;
# accept RCON traffic that comes from the same machine, for things like SourceBans&lt;br /&gt;
# if you know you aren't using anything else that relies on RCON you may omit this&lt;br /&gt;
# if legitimate RCON traffic may come from elsewhere, change the source network (-s 127.0.0.1/8),&lt;br /&gt;
# or append additional rules for addresses that should be allowed&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -s 127.0.0.1/8 -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
# drop everything else going to the game port&lt;br /&gt;
iptables -A INPUT -p tcp --dport 27015 -j DROP&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Platform-specific =&lt;br /&gt;
&lt;br /&gt;
== Linux extension failing to load on outdated &amp;lt;tt&amp;gt;GLIBCXX_*&amp;lt;/tt&amp;gt; version ==&lt;br /&gt;
&lt;br /&gt;
Various Source Engine games (Counter Strike: Source, Day of Defeat: Source, Counter Strike: Global Offensive, third-party games using the Source SDK modding system, possibly others) bundle standard libraries that are older than what current operating systems ship with, but newer than those that Valve ships as a baseline.&lt;br /&gt;
&lt;br /&gt;
Software that depends on new versions of libraries will fail to load.  This includes Metamod:Source, SourceMod, and other native code / plugins / extension.&lt;br /&gt;
&lt;br /&gt;
You can choose to do one of the following:&lt;br /&gt;
&lt;br /&gt;
* Remove any existing copies of &amp;lt;tt&amp;gt;bin/libstdc++.so.6&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to your game install directory (not the root of the filesytem); this will let the game load the system libraries.&lt;br /&gt;
** If you are on a 64-bit system, continue to the [[#64-bit_Linux_systems_and_32-bit_executables|next section]] to ensure the system's 32-bit libraries are actually available after removing the Valve-bundled copies.&lt;br /&gt;
* If your operating system is also dated, you will need rebuild the extension using an older build environment, or upgrade to a newer one.  If you plan on recompiling the extension, the [https://github.com/ValveSoftware/steam-runtime Steam Runtime SDK] is considered the baseline of support.&lt;br /&gt;
&lt;br /&gt;
== 64-bit Linux systems and 32-bit executables ==&lt;br /&gt;
&lt;br /&gt;
[https://sporks.space/2022/02/27/win32-is-the-stable-linux-userland-abi-and-the-consequences/ Unlike Windows], 64-bit Linux systems are not guaranteed to ship with full compatibility for 32-bit executables by default.&lt;br /&gt;
&lt;br /&gt;
Depending on your distribution, you will need to run one of the following commands as root to install the required packages / libraries:&lt;br /&gt;
&lt;br /&gt;
* Debian / Ubuntu: &amp;lt;tt&amp;gt;apt install gcc-multilib&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Arch: &amp;lt;tt&amp;gt;pacman -S lib32-gcc-libs&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Fedora: &amp;lt;tt&amp;gt;yum -y install glibc.i686&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Game Specific =&lt;br /&gt;
&lt;br /&gt;
== Team Fortress 2 ==&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.teamfortress.com/wiki/Dedicated_server_configuration Dedicated server configuration] section on the Team Fortress 2 Official Wiki provides general configuration instructions.  Depending on the platform you're working on, you may also be interested in the sections for [https://wiki.teamfortress.com/wiki/Linux_dedicated_server Linux] and [https://wiki.teamfortress.com/wiki/Windows_dedicated_server Windows].&lt;br /&gt;
&lt;br /&gt;
=== Mann vs. Machine ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;tt&amp;gt;tf_mvm_min_players_to_start&amp;lt;/tt&amp;gt; to 1 to only require one player to ready up and start the mission.&lt;br /&gt;
&lt;br /&gt;
=== Steam Datagram Relay ===&lt;br /&gt;
&lt;br /&gt;
The Steam Datagram Relay routes both server and client connections through the Steam network, hiding the IP address of each from the other.&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;tt&amp;gt;-enablefakeip&amp;lt;/tt&amp;gt; in the server's launch options to enable.  The server will then report &amp;quot;FakeIP allocation succeeded&amp;quot; at the end of startup; use that IP address / port combination in your game client to connect to the server.  This allocation will change on every server startup.&lt;br /&gt;
&lt;br /&gt;
=== Games that aren't ===&lt;br /&gt;
&lt;br /&gt;
Non-exhaustive list of Source Engine class-based shooters with a cartoon-like visual style based on the art of Dean Cornwell, J. C. Leyendecker, and Norman Rockwell, that aren't [https://store.steampowered.com/app/440/Team_Fortress_2/ Team Fortress 2]:&lt;br /&gt;
&lt;br /&gt;
* Team Fortress 2 Classic&lt;br /&gt;
* Open Fortress&lt;br /&gt;
&lt;br /&gt;
If you're developing plugins and asking questions about one of those games, please specifically name them.  These games are not guaranteed to behave the same as &amp;quot;retail&amp;quot; Team Fortress 2, and solutions that work for retail aren't guaranteed to work on third-party mods.&lt;br /&gt;
&lt;br /&gt;
== Counter-Strike: Global Offensive ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Dedicated_Servers#Advanced_Configuration Advanced Configuration] section on the Valve Developer Wiki describes server configuration unique to CS:GO. It's different from most other mods.&lt;br /&gt;
&lt;br /&gt;
=== Responsive server console when hibernating ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;sv_hibernate_ms&amp;lt;/code&amp;gt; to 0 to make the server console more responsive when no players are online.&lt;br /&gt;
&lt;br /&gt;
== Left 4 Dead 2 ==&lt;br /&gt;
&lt;br /&gt;
=== Disabling lobby system ===&lt;br /&gt;
&lt;br /&gt;
While developing plugins, you generally don't want players being connected through Steam's lobby system.  Add the following to &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_allow_lobby_connect_only &amp;quot;0&amp;quot;;&lt;br /&gt;
sv_password &amp;quot;password_to_connect_with&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Virtual Server Configuration =&lt;br /&gt;
&lt;br /&gt;
As a developer, you may need to test on multiple platforms. To avoid having another physical machine to work on, you can use virtualization to run an operating system on your desktop.&lt;br /&gt;
&lt;br /&gt;
== Virtualbox ==&lt;br /&gt;
&lt;br /&gt;
=== Networking ===&lt;br /&gt;
&lt;br /&gt;
==== Network Address Translation ====&lt;br /&gt;
&lt;br /&gt;
With NAT plus port forwarding, the minimum would be to forward UDP from one of the host's loopback IP addresses to the server port on the VM's address.  Forwarding TCP isn't necessary unless you are interested in using the RCON protocol.&lt;br /&gt;
&lt;br /&gt;
For example, given a virtual machine with an IP address of &amp;lt;tt&amp;gt;10.0.2.15&amp;lt;/tt&amp;gt; and the server listening on port 27015, you should configure NAT as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt; (host) &amp;amp;rarr; &amp;lt;tt&amp;gt;10.0.2.15:27015&amp;lt;/tt&amp;gt; (guest)&lt;br /&gt;
&lt;br /&gt;
You can then connect to the server from the host OS by connecting to &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Any loopback IP address on the host portion is acceptable to use (that is, any address starting with &amp;lt;tt&amp;gt;127.*.*.*&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Host-Only Adapter ====&lt;br /&gt;
&lt;br /&gt;
Enable the Host-Only Adapter on your VM and statically assign the address to be in the same network as your host operating system's adapter. This allows you to connect to the server without any additional networking complexities.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11435</id>
		<title>User:Nosoop/Guide/Advanced</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11435"/>
		<updated>2023-05-08T09:18:50Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: Add primer on gamedata&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section is provided for users that want or need to work with game-specific functionality that SourceMod doesn't provide access to out of the box.&lt;br /&gt;
&lt;br /&gt;
It's assumed that you're comfortable with programming and various terms.  By the end of this page you'll have some knowledge of calling / hooking arbitrary functions in the game.&lt;br /&gt;
&lt;br /&gt;
= What is gamedata? =&lt;br /&gt;
&lt;br /&gt;
''Gamedata'', also known as game data, gameconfig, and gameconf, are files used to specify information tied to a specific game.&lt;br /&gt;
&lt;br /&gt;
As the games that SourceMod runs on are updated independently of SourceMod itself, gamedata is used as a unified way to keep plugins and extensions up to date on game changes without needing to recompile them.&lt;br /&gt;
&lt;br /&gt;
= Finding Functions =&lt;br /&gt;
&lt;br /&gt;
* TODO refer to public SDK if you don't know what you're looking for&lt;br /&gt;
* TODO explain what to do in a game with symbols&lt;br /&gt;
* TODO suggest opening IDA's options and enabling opcode bytes&lt;br /&gt;
* TODO inlined functions&lt;br /&gt;
* TODO debugging&lt;br /&gt;
&lt;br /&gt;
= Finding VTable Offsets =&lt;br /&gt;
&lt;br /&gt;
In C++, a ''virtual method table'' (shorthand &amp;amp;quot;vtable&amp;amp;quot;) is effectively an array of function pointers. It's intended for inheritance — a virtual &amp;lt;code&amp;gt;::DoThing()&amp;lt;/code&amp;gt; method can be different for different classes, and so the code will look up the correct function for a specific instance based on the table for the instance's class. Every class that uses a vtable will hold a reference to it as one of its properties.&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
Once you have the virtual call, jump to its reference in &amp;lt;tt&amp;gt;.rodata&amp;lt;/tt&amp;gt; and make a note of that address.  Scroll up until you see an offset reference (&amp;lt;tt&amp;gt;off_*&amp;lt;/tt&amp;gt; in IDA, &amp;lt;tt&amp;gt;PTR_*&amp;lt;/tt&amp;gt; in Ghidra); that is likely the first entry in the vtable (index 0).  This reference is created by disassemblers as this is the address that is stored in class instances.&lt;br /&gt;
&lt;br /&gt;
Get the difference between your virtual call's address and that of the first entry, then divide by the pointer size (4 on 32-bit platforms, 8 on 64-bit).&lt;br /&gt;
&lt;br /&gt;
For example, given a 32-bit function pointer located at &amp;lt;tt&amp;gt;011AE84Ch&amp;lt;/tt&amp;gt; and the start at &amp;lt;tt&amp;gt;011AE3C8h&amp;lt;/tt&amp;gt;, you do &amp;lt;tt&amp;gt;(0x011AE84C-0x011AE3C8) / 4&amp;lt;/tt&amp;gt;, resulting in the index 289.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if you're familiar with the code or have sources to cross-reference against, you can search for the virtual call itself.  In a Linux disassembly, it will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; get the first vtable by dereferencing the pointer at the start of the class instance&lt;br /&gt;
8B 03       mov  eax, [ebx]&lt;br /&gt;
&lt;br /&gt;
; push the class instance as a parameter&lt;br /&gt;
89 1C 24    mov  [esp], ebx&lt;br /&gt;
&lt;br /&gt;
; call the fourth entry (at index 3) in the vtable: 0xC / sizeof(void*) = 0x3&lt;br /&gt;
FF 50 0C    call dword ptr [eax+0Ch]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If the game isn't stripped of debugging symbols, use [https://asherkin.github.io/vtable/ asherkin's VTable Dumper].  It provides correct offsets for Linux binaries (as it's what it works with), and estimates usually correct offsets for Windows.&lt;br /&gt;
&lt;br /&gt;
There are instances where the dumper isn't correct, so you may need to be careful in those cases.  Known cases include:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/asherkin/vtable/issues/7 Classes that have discontinuous overloaded functions]&lt;br /&gt;
* Possibly multiple inheritance&lt;br /&gt;
&lt;br /&gt;
Aside - the layout of vtables is not the same across platforms.  Notable differences are:&lt;br /&gt;
&lt;br /&gt;
# Linux may have multiple virtual destructors; Windows appears to only have up to one.&lt;br /&gt;
# Linux overloads are in the same order as they are initially defined in the original code.  On Windows, this is the same, except that overloaded functions (those with the same name that accept different parameters) are grouped together and emitted in reverse order.&lt;br /&gt;
&lt;br /&gt;
= Creating Signatures =&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
After you've found a function, you need to tell SourceMod the sequence of bytes unique to it. Those bytes make up a ''signature''.&lt;br /&gt;
&lt;br /&gt;
{{Note|If you're using IDA and only see the mnemonics in the &amp;quot;IDA View&amp;quot; tab, make sure to set the number of opcode bytes in IDA options to a non-zero number.  8 is sufficient in most cases.}}&lt;br /&gt;
&lt;br /&gt;
You could treat just the sequence bytes as the signature directly, but this would break very easily whenever the game is updated. At the machine-code level, the ''instructions'' might be the same for &amp;amp;quot;move X to Y&amp;amp;quot;, but the ''data'' might change — X and Y might be in a different location in the binary altogether. For an example within a longer signature:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; sets esp to the offset aString&lt;br /&gt;
; the bytes 3B B3 25 01 are the absolute offset of aString in this binary in little-endian format (0x0125B33B)&lt;br /&gt;
C7 04 24 3B B3 25 01    mov     dword ptr [esp], offset aString&lt;br /&gt;
&lt;br /&gt;
; call function, the four bytes after E8 are the location of the function&lt;br /&gt;
E8 78 F0 48 00          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
&lt;br /&gt;
; sets eax to arg 0&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The naive signature for that would be &amp;lt;code&amp;gt;\xC7\x04\x24\x3B\xB3\x25\x01\xE8\x78\xF0\x48\x00\x8B\x45\x08&amp;lt;/code&amp;gt;. However, you can't rely on those bytes mentioned to be constant at all:&lt;br /&gt;
&lt;br /&gt;
* The offsets of &amp;lt;code&amp;gt;aString&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UTIL_VarArgs&amp;lt;/code&amp;gt; might be located somewhere else after a game update&lt;br /&gt;
* Relocations may be performed such that the data bytes are different in memory from its on-disk representation&lt;br /&gt;
&lt;br /&gt;
As a solution to this, you use wildcards to mask off the bytes you don't care about. For SourceMod game config files, the sequence &amp;lt;code&amp;gt;\x2A&amp;lt;/code&amp;gt; indicates that particular byte shouldn't be checked and to continue to the next one.&lt;br /&gt;
&lt;br /&gt;
Here is what the previous signature looks like with the masked bytes displayed as &amp;lt;code&amp;gt;??&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
C7 04 24 ?? ?? ?? ??    mov     dword ptr [esp], offset aString&lt;br /&gt;
E8 ?? ?? ?? ??          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A masked signature would then be &amp;lt;code&amp;gt;\xC7\x04\x24\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x45\x08&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Masking is used mainly for offsets, such as for functions and variables. Instructions generally don't change unless the function code itself is modified, at which point you'll want to revisit your binary and update accordingly.&lt;br /&gt;
&lt;br /&gt;
If you're using DHooks with byte signatures (covered later), you may want to also mask out the first six bytes, as a detour will patch in an unconditional JMP at the start to trampoline into a user-defined function, and subsequent scans for the byte signature will fail.&lt;br /&gt;
&lt;br /&gt;
{{Note|This is no longer the case as of SourceMod 1.11, which stores a copy of the original data for scanning purposes.  However, it's noted here for historical / implementation detail reasons.}}&lt;br /&gt;
&lt;br /&gt;
For an extended lesson, you can look at the following material:&lt;br /&gt;
&lt;br /&gt;
* [https://wiki.alliedmods.net/Signature_Scanning Signature Scanning] on the AlliedModders wiki&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If you're using IDA (including Free), use the [https://github.com/alliedmodders/sourcemod/blob/master/tools/ida_scripts/makesig7.idc &amp;lt;code&amp;gt;makesig7.idc&amp;lt;/code&amp;gt;] script. If you're using Ghidra, use [https://github.com/alliedmodders/sourcemod/blob/master/tools/ghidra_scripts/makesig.py &amp;lt;code&amp;gt;makesig.py&amp;lt;/code&amp;gt;].&lt;br /&gt;
&lt;br /&gt;
They generally do pretty well at finding and masking byte signatures, but when it fails or you want a more robust signature, you should understand how to create the signatures manually.&lt;br /&gt;
&lt;br /&gt;
Both scripts may produce different byte signatures for the same function due to using different methods to determine if a given byte should be masked.&lt;br /&gt;
&lt;br /&gt;
It's exceedingly rare, but possible that the binary has two copies of the exact same short function (for example, when they are typechecked and statically casted to different subclasses). Both scripts will fail in that case. SourceMod's signature scanner will use the first match it finds, so if any match is acceptable, you can still use an appropriately masked signature.&lt;br /&gt;
&lt;br /&gt;
If two copies of a function seem to exist, be sure to look at the disassembly to make sure that the functions are indeed the same.&lt;br /&gt;
&lt;br /&gt;
= Finding Addresses =&lt;br /&gt;
&lt;br /&gt;
Sometimes you have a symbol, but you need an address to work with.  That is what the &amp;quot;Addresses&amp;quot; section of a game configuration file is used for.&lt;br /&gt;
&lt;br /&gt;
To find an address, you start from a known location reference (signature).  You may then have to jump to references (that is, dereference locations), then get an offset from the previous reference.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; keys indicate an offset to load / dereference relative to the previous address, and &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; means to shift the previous address without any dereference.  These key / value pairs are processed in the order you specify them in the file; &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; is only valid as the last &amp;quot;operation&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For a C++-like example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// start from an address&lt;br /&gt;
// &amp;quot;FindLocation&amp;quot; would return the location of either a named symbol reference or the start of a byte signature&lt;br /&gt;
uintptr_t addr = FindLocation(&amp;quot;some_signature&amp;quot;);&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr + 40); // gameconf: &amp;quot;read&amp;quot; &amp;quot;40&amp;quot;&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr); // gameconf: &amp;quot;read&amp;quot; &amp;quot;0&amp;quot;&lt;br /&gt;
addr += 13; // gameconf: &amp;quot;offset&amp;quot; &amp;quot;13&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Calling Game Functions =&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== SDKCall Order ==&lt;br /&gt;
&lt;br /&gt;
When performing an {{SourceMod API|file=sdktools|function=SDKCall}}, the parameters need to be passed in the following order:&lt;br /&gt;
&lt;br /&gt;
# The SDKCall handle received from {{SourceMod API|file=sdktools|function=EndPrepSDKCall}}.&lt;br /&gt;
# The &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; instance.  &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; may be omitted in the following cases:&lt;br /&gt;
#* The function was declared as static, where there is no &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; to pass in.&lt;br /&gt;
#* The function was declared with the &amp;lt;tt&amp;gt;SDKCall_GameRules&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SDKCall_EntityList&amp;lt;/tt&amp;gt; call types; SDKTools itself will provide the appropriate global instance.&lt;br /&gt;
# The return buffer, if applicable.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;Vector&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;QAngle&amp;lt;/tt&amp;gt;, the parameter is a &amp;lt;tt&amp;gt;float[3]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt;, the parameters should be a &amp;lt;tt&amp;gt;char[]&amp;lt;/tt&amp;gt; buffer and an &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; specifying the size of the buffer.  The return value of the SDKCall will be the number of characters written, or -1 if the function returned a null pointer (to differentiate between an empty string).&lt;br /&gt;
#* If the function returns a primitive type / entity / edict, it will be the return value of the SDKCall, so no such return buffer is necessary.&lt;br /&gt;
# Any remaining parameters for the function.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// Vector CBaseCombatCharacter::Weapon_ShootPosition() -- has 'this' and 'Vector' return&lt;br /&gt;
float vecShootPosition[3];&lt;br /&gt;
SDKCall(g_hSDKCall, client, vecShootPosition);&lt;br /&gt;
&lt;br /&gt;
// const char *CBaseAnimating::GetSequenceName(int iSequence) -- has 'this', 'char*' return, and parameter&lt;br /&gt;
char sequenceName[64];&lt;br /&gt;
SDKCall(g_hSDKCall, entity, sequenceName, sizeof(sequenceName), iSequence);&lt;br /&gt;
&lt;br /&gt;
// bool CGlobalEntityList::IsEntityPtr(void* pTest) -- SDKCall_EntityList is used, so no 'this' explicitly needed&lt;br /&gt;
// SDKCall passes the return value from the called function as its return value, so use an assignment operator&lt;br /&gt;
bool result = SDKCall(g_hSDKCall, pTest);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Hooking Game Functions (with DHooks) =&lt;br /&gt;
&lt;br /&gt;
DHooks is an extension bundled with SourceMod that enables plugins to hook functions of their choosing (currently restricted to those accessible via server / engine binaries).  You may use its functionality by including {{SourceMod API|file=dhooks}}.&lt;br /&gt;
&lt;br /&gt;
As with {{SourceMod API|file=sdktools|function=SDKCall}}s, you must ensure that your hook setup is declared with the same parameter and return types to ensure the server continues to operate as you'd expect.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== Virtual Hook or Detour? ==&lt;br /&gt;
&lt;br /&gt;
A virtual hook is mainly used for hooking virtual methods of a class; a detour is used for hooking any function.&lt;br /&gt;
&lt;br /&gt;
While detours can be used to hook the function a virtual table calls into, virtual hooks still have the merit of hooking specific classes / instances.  More specifically:&lt;br /&gt;
&lt;br /&gt;
* DHooks provides the bookkeeping on which instances are and aren't hooked, so for virtual hooks the callback will only be invoked on those you specifically hook.  On detours, you have to filter on instances yourself.&lt;br /&gt;
* On chained inheritance, a virtual hook will only act on the exact class and not any parent nor subclasses, even if they all point to the same virtual function.  Detours will, again, be called on any invocation of the function, including calls to it made by its subclass.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11434</id>
		<title>User:Nosoop/Guide/Advanced</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Advanced&amp;diff=11434"/>
		<updated>2023-04-16T10:39:25Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* SDKCall Order */ Put return buffer items into a list; add notes on string return&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section is provided for users that want or need to work with game-specific functionality that SourceMod doesn't provide access to out of the box.&lt;br /&gt;
&lt;br /&gt;
It's assumed that you're comfortable with programming and various terms.  By the end of this page you'll have some knowledge of calling / hooking arbitrary functions in the game.&lt;br /&gt;
&lt;br /&gt;
= Finding Functions =&lt;br /&gt;
&lt;br /&gt;
* TODO refer to public SDK if you don't know what you're looking for&lt;br /&gt;
* TODO explain what to do in a game with symbols&lt;br /&gt;
* TODO suggest opening IDA's options and enabling opcode bytes&lt;br /&gt;
* TODO inlined functions&lt;br /&gt;
* TODO debugging&lt;br /&gt;
&lt;br /&gt;
= Finding VTable Offsets =&lt;br /&gt;
&lt;br /&gt;
In C++, a ''virtual method table'' (shorthand &amp;amp;quot;vtable&amp;amp;quot;) is effectively an array of function pointers. It's intended for inheritance — a virtual &amp;lt;code&amp;gt;::DoThing()&amp;lt;/code&amp;gt; method can be different for different classes, and so the code will look up the correct function for a specific instance based on the table for the instance's class. Every class that uses a vtable will hold a reference to it as one of its properties.&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
Once you have the virtual call, jump to its reference in &amp;lt;tt&amp;gt;.rodata&amp;lt;/tt&amp;gt; and make a note of that address.  Scroll up until you see an offset reference (&amp;lt;tt&amp;gt;off_*&amp;lt;/tt&amp;gt; in IDA, &amp;lt;tt&amp;gt;PTR_*&amp;lt;/tt&amp;gt; in Ghidra); that is likely the first entry in the vtable (index 0).  This reference is created by disassemblers as this is the address that is stored in class instances.&lt;br /&gt;
&lt;br /&gt;
Get the difference between your virtual call's address and that of the first entry, then divide by the pointer size (4 on 32-bit platforms, 8 on 64-bit).&lt;br /&gt;
&lt;br /&gt;
For example, given a 32-bit function pointer located at &amp;lt;tt&amp;gt;011AE84Ch&amp;lt;/tt&amp;gt; and the start at &amp;lt;tt&amp;gt;011AE3C8h&amp;lt;/tt&amp;gt;, you do &amp;lt;tt&amp;gt;(0x011AE84C-0x011AE3C8) / 4&amp;lt;/tt&amp;gt;, resulting in the index 289.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if you're familiar with the code or have sources to cross-reference against, you can search for the virtual call itself.  In a Linux disassembly, it will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; get the first vtable by dereferencing the pointer at the start of the class instance&lt;br /&gt;
8B 03       mov  eax, [ebx]&lt;br /&gt;
&lt;br /&gt;
; push the class instance as a parameter&lt;br /&gt;
89 1C 24    mov  [esp], ebx&lt;br /&gt;
&lt;br /&gt;
; call the fourth entry (at index 3) in the vtable: 0xC / sizeof(void*) = 0x3&lt;br /&gt;
FF 50 0C    call dword ptr [eax+0Ch]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If the game isn't stripped of debugging symbols, use [https://asherkin.github.io/vtable/ asherkin's VTable Dumper].  It provides correct offsets for Linux binaries (as it's what it works with), and estimates usually correct offsets for Windows.&lt;br /&gt;
&lt;br /&gt;
There are instances where the dumper isn't correct, so you may need to be careful in those cases.  Known cases include:&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/asherkin/vtable/issues/7 Classes that have discontinuous overloaded functions]&lt;br /&gt;
* Possibly multiple inheritance&lt;br /&gt;
&lt;br /&gt;
Aside - the layout of vtables is not the same across platforms.  Notable differences are:&lt;br /&gt;
&lt;br /&gt;
# Linux may have multiple virtual destructors; Windows appears to only have up to one.&lt;br /&gt;
# Linux overloads are in the same order as they are initially defined in the original code.  On Windows, this is the same, except that overloaded functions (those with the same name that accept different parameters) are grouped together and emitted in reverse order.&lt;br /&gt;
&lt;br /&gt;
= Creating Signatures =&lt;br /&gt;
&lt;br /&gt;
== The Hard Way ==&lt;br /&gt;
&lt;br /&gt;
After you've found a function, you need to tell SourceMod the sequence of bytes unique to it. Those bytes make up a ''signature''.&lt;br /&gt;
&lt;br /&gt;
{{Note|If you're using IDA and only see the mnemonics in the &amp;quot;IDA View&amp;quot; tab, make sure to set the number of opcode bytes in IDA options to a non-zero number.  8 is sufficient in most cases.}}&lt;br /&gt;
&lt;br /&gt;
You could treat just the sequence bytes as the signature directly, but this would break very easily whenever the game is updated. At the machine-code level, the ''instructions'' might be the same for &amp;amp;quot;move X to Y&amp;amp;quot;, but the ''data'' might change — X and Y might be in a different location in the binary altogether. For an example within a longer signature:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; sets esp to the offset aString&lt;br /&gt;
; the bytes 3B B3 25 01 are the absolute offset of aString in this binary in little-endian format (0x0125B33B)&lt;br /&gt;
C7 04 24 3B B3 25 01    mov     dword ptr [esp], offset aString&lt;br /&gt;
&lt;br /&gt;
; call function, the four bytes after E8 are the location of the function&lt;br /&gt;
E8 78 F0 48 00          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
&lt;br /&gt;
; sets eax to arg 0&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The naive signature for that would be &amp;lt;code&amp;gt;\xC7\x04\x24\x3B\xB3\x25\x01\xE8\x78\xF0\x48\x00\x8B\x45\x08&amp;lt;/code&amp;gt;. However, you can't rely on those bytes mentioned to be constant at all:&lt;br /&gt;
&lt;br /&gt;
* The offsets of &amp;lt;code&amp;gt;aString&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UTIL_VarArgs&amp;lt;/code&amp;gt; might be located somewhere else after a game update&lt;br /&gt;
* Relocations may be performed such that the data bytes are different in memory from its on-disk representation&lt;br /&gt;
&lt;br /&gt;
As a solution to this, you use wildcards to mask off the bytes you don't care about. For SourceMod game config files, the sequence &amp;lt;code&amp;gt;\x2A&amp;lt;/code&amp;gt; indicates that particular byte shouldn't be checked and to continue to the next one.&lt;br /&gt;
&lt;br /&gt;
Here is what the previous signature looks like with the masked bytes displayed as &amp;lt;code&amp;gt;??&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
C7 04 24 ?? ?? ?? ??    mov     dword ptr [esp], offset aString&lt;br /&gt;
E8 ?? ?? ?? ??          call    _Z12UTIL_VarArgsPKcz&lt;br /&gt;
8B 45 08                mov     eax, [ebp+arg_0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A masked signature would then be &amp;lt;code&amp;gt;\xC7\x04\x24\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x45\x08&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Masking is used mainly for offsets, such as for functions and variables. Instructions generally don't change unless the function code itself is modified, at which point you'll want to revisit your binary and update accordingly.&lt;br /&gt;
&lt;br /&gt;
If you're using DHooks with byte signatures (covered later), you may want to also mask out the first six bytes, as a detour will patch in an unconditional JMP at the start to trampoline into a user-defined function, and subsequent scans for the byte signature will fail.&lt;br /&gt;
&lt;br /&gt;
{{Note|This is no longer the case as of SourceMod 1.11, which stores a copy of the original data for scanning purposes.  However, it's noted here for historical / implementation detail reasons.}}&lt;br /&gt;
&lt;br /&gt;
For an extended lesson, you can look at the following material:&lt;br /&gt;
&lt;br /&gt;
* [https://wiki.alliedmods.net/Signature_Scanning Signature Scanning] on the AlliedModders wiki&lt;br /&gt;
&lt;br /&gt;
== The Easy Way ==&lt;br /&gt;
&lt;br /&gt;
If you're using IDA (including Free), use the [https://github.com/alliedmodders/sourcemod/blob/master/tools/ida_scripts/makesig7.idc &amp;lt;code&amp;gt;makesig7.idc&amp;lt;/code&amp;gt;] script. If you're using Ghidra, use [https://github.com/alliedmodders/sourcemod/blob/master/tools/ghidra_scripts/makesig.py &amp;lt;code&amp;gt;makesig.py&amp;lt;/code&amp;gt;].&lt;br /&gt;
&lt;br /&gt;
They generally do pretty well at finding and masking byte signatures, but when it fails or you want a more robust signature, you should understand how to create the signatures manually.&lt;br /&gt;
&lt;br /&gt;
Both scripts may produce different byte signatures for the same function due to using different methods to determine if a given byte should be masked.&lt;br /&gt;
&lt;br /&gt;
It's exceedingly rare, but possible that the binary has two copies of the exact same short function (for example, when they are typechecked and statically casted to different subclasses). Both scripts will fail in that case. SourceMod's signature scanner will use the first match it finds, so if any match is acceptable, you can still use an appropriately masked signature.&lt;br /&gt;
&lt;br /&gt;
If two copies of a function seem to exist, be sure to look at the disassembly to make sure that the functions are indeed the same.&lt;br /&gt;
&lt;br /&gt;
= Finding Addresses =&lt;br /&gt;
&lt;br /&gt;
Sometimes you have a symbol, but you need an address to work with.  That is what the &amp;quot;Addresses&amp;quot; section of a game configuration file is used for.&lt;br /&gt;
&lt;br /&gt;
To find an address, you start from a known location reference (signature).  You may then have to jump to references (that is, dereference locations), then get an offset from the previous reference.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; keys indicate an offset to load / dereference relative to the previous address, and &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; means to shift the previous address without any dereference.  These key / value pairs are processed in the order you specify them in the file; &amp;lt;code&amp;gt;offset&amp;lt;/code&amp;gt; is only valid as the last &amp;quot;operation&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For a C++-like example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// start from an address&lt;br /&gt;
// &amp;quot;FindLocation&amp;quot; would return the location of either a named symbol reference or the start of a byte signature&lt;br /&gt;
uintptr_t addr = FindLocation(&amp;quot;some_signature&amp;quot;);&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr + 40); // gameconf: &amp;quot;read&amp;quot; &amp;quot;40&amp;quot;&lt;br /&gt;
addr = *reinterpret_cast&amp;lt;uintptr_t*&amp;gt;(addr); // gameconf: &amp;quot;read&amp;quot; &amp;quot;0&amp;quot;&lt;br /&gt;
addr += 13; // gameconf: &amp;quot;offset&amp;quot; &amp;quot;13&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Calling Game Functions =&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== SDKCall Order ==&lt;br /&gt;
&lt;br /&gt;
When performing an {{SourceMod API|file=sdktools|function=SDKCall}}, the parameters need to be passed in the following order:&lt;br /&gt;
&lt;br /&gt;
# The SDKCall handle received from {{SourceMod API|file=sdktools|function=EndPrepSDKCall}}.&lt;br /&gt;
# The &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; instance.  &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; may be omitted in the following cases:&lt;br /&gt;
#* The function was declared as static, where there is no &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; to pass in.&lt;br /&gt;
#* The function was declared with the &amp;lt;tt&amp;gt;SDKCall_GameRules&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SDKCall_EntityList&amp;lt;/tt&amp;gt; call types; SDKTools itself will provide the appropriate global instance.&lt;br /&gt;
# The return buffer, if applicable.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;Vector&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;QAngle&amp;lt;/tt&amp;gt;, the parameter is a &amp;lt;tt&amp;gt;float[3]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
#* If the function returns a &amp;lt;tt&amp;gt;char*&amp;lt;/tt&amp;gt;, the parameters should be a &amp;lt;tt&amp;gt;char[]&amp;lt;/tt&amp;gt; buffer and an &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; specifying the size of the buffer.  The return value of the SDKCall will be the number of characters written, or -1 if the function returned a null pointer (to differentiate between an empty string).&lt;br /&gt;
#* If the function returns a primitive type / entity / edict, it will be the return value of the SDKCall, so no such return buffer is necessary.&lt;br /&gt;
# Any remaining parameters for the function.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;cpp&amp;quot;&amp;gt;// Vector CBaseCombatCharacter::Weapon_ShootPosition() -- has 'this' and 'Vector' return&lt;br /&gt;
float vecShootPosition[3];&lt;br /&gt;
SDKCall(g_hSDKCall, client, vecShootPosition);&lt;br /&gt;
&lt;br /&gt;
// const char *CBaseAnimating::GetSequenceName(int iSequence) -- has 'this', 'char*' return, and parameter&lt;br /&gt;
char sequenceName[64];&lt;br /&gt;
SDKCall(g_hSDKCall, entity, sequenceName, sizeof(sequenceName), iSequence);&lt;br /&gt;
&lt;br /&gt;
// bool CGlobalEntityList::IsEntityPtr(void* pTest) -- SDKCall_EntityList is used, so no 'this' explicitly needed&lt;br /&gt;
// SDKCall passes the return value from the called function as its return value, so use an assignment operator&lt;br /&gt;
bool result = SDKCall(g_hSDKCall, pTest);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Hooking Game Functions (with DHooks) =&lt;br /&gt;
&lt;br /&gt;
DHooks is an extension bundled with SourceMod that enables plugins to hook functions of their choosing (currently restricted to those accessible via server / engine binaries).  You may use its functionality by including {{SourceMod API|file=dhooks}}.&lt;br /&gt;
&lt;br /&gt;
As with {{SourceMod API|file=sdktools|function=SDKCall}}s, you must ensure that your hook setup is declared with the same parameter and return types to ensure the server continues to operate as you'd expect.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
== Virtual Hook or Detour? ==&lt;br /&gt;
&lt;br /&gt;
A virtual hook is mainly used for hooking virtual methods of a class; a detour is used for hooking any function.&lt;br /&gt;
&lt;br /&gt;
While detours can be used to hook the function a virtual table calls into, virtual hooks still have the merit of hooking specific classes / instances.  More specifically:&lt;br /&gt;
&lt;br /&gt;
* DHooks provides the bookkeeping on which instances are and aren't hooked, so for virtual hooks the callback will only be invoked on those you specifically hook.  On detours, you have to filter on instances yourself.&lt;br /&gt;
* On chained inheritance, a virtual hook will only act on the exact class and not any parent nor subclasses, even if they all point to the same virtual function.  Detours will, again, be called on any invocation of the function, including calls to it made by its subclass.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11433</id>
		<title>User:Nosoop/Guide/Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11433"/>
		<updated>2023-04-16T10:30:48Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: Insert notes on comments&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;At this point you should have a server to test plugins on and a full development environment to write plugins with.&lt;br /&gt;
&lt;br /&gt;
= Hello! =&lt;br /&gt;
&lt;br /&gt;
As is tradition with other programming languages, we'll start with something that outputs &amp;lt;code&amp;gt;Hello, world!&amp;lt;/code&amp;gt; in some form. In this case, you'll install the plugin on your server and load it; the message will be printed in the server console.&lt;br /&gt;
&lt;br /&gt;
Open up your editor, and enter the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
// this is a comment&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save this file as &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt;. SourcePawn scripts always contain the &amp;lt;code&amp;gt;.sp&amp;lt;/code&amp;gt; extension.&lt;br /&gt;
&lt;br /&gt;
Compile your code. Refer to your [[../Development Environments|IDE-specific documentation]] for this.&lt;br /&gt;
&lt;br /&gt;
On a successful compile, you should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
Code size:             2960 bytes&lt;br /&gt;
Data size:             2240 bytes&lt;br /&gt;
Stack/heap size:      16384 bytes&lt;br /&gt;
Total requirements:   21584 bytes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first few lines may be slightly different between SourceMod compiler versions, but as long as you see the four &amp;amp;quot;bytes&amp;amp;quot; lines, you've successfully compiled the plugin, and you should have a &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
If there was an error in compilation, you'll see something like this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
01_hello.sp(4 -- 5) : error 001: expected token: &amp;quot;,&amp;quot;, but found &amp;quot;}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
1 Error.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You'll need to be able to read these sorts of error messages and understand the common ones, because no developer is immune to writing code without any errors all the time.&lt;br /&gt;
&lt;br /&gt;
In this case, the compiler tells us that my &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt; (intentionally made to fail - the code above should compile correctly) has an error around lines 4 and 5, and gives us information about what caused it to not compile the code.&lt;br /&gt;
&lt;br /&gt;
{{Note|Warnings are not errors.&lt;br /&gt;
Learn to differentiate between the two.  If you get a lot of messages when compiling a large plugin, prioritize resolving the errors.  It's possible that some syntax error is causing all sorts of warnings down the line.}}&lt;br /&gt;
&lt;br /&gt;
== Running the Plugin ==&lt;br /&gt;
&lt;br /&gt;
Copy the &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file to your game server's &amp;lt;code&amp;gt;addons/sourcemod/plugins/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
If the server is already running, get to the server console and type &amp;lt;code&amp;gt;sm plugins load 01_hello&amp;lt;/code&amp;gt; to load the plugin. You should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello, world!&lt;br /&gt;
[SM] Loaded plugin 01_hello.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If so, congratulations! You just wrote your first plugin.&lt;br /&gt;
&lt;br /&gt;
== What's in a Plugin ==&lt;br /&gt;
&lt;br /&gt;
Adding text to a file, compiling it, and running the resulting plugin is one thing; it's much more important to understand what the text you're writing actually does.&lt;br /&gt;
&lt;br /&gt;
We'll start from the top:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line is a ''preprocessor directive''. Lines starting with &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; are instructions for the compiler (rather, the preprocessor that examines the code before compilation occurs). In this case, &amp;lt;code&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&amp;lt;/code&amp;gt; tells the preprocessor to include the files that make up SourceMod's standard library.  There are other first- and third-party libraries that you may want to include later on.&lt;br /&gt;
&lt;br /&gt;
Immediately after the line is a blank line. It serves no other purpose other than to visually organize code, but organization is good.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;// this is a comment&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two forward slashes (&amp;lt;code&amp;gt;//&amp;lt;/code&amp;gt;) indicate the start of a start of a single-line comment.  Single-line comments start from those forward slashes and continue up until the end of the line of text.  Comments are not compiled into the actual code, but serve as informational pieces of text for the reader.  These will be used later in the guide to streamline reading.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;public void OnPluginStart() {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line defines a function named {{SourceMod API|file=sourcemod|function=OnPluginStart}} in SourceMod (click the link to see the documentation for it). It is a ''forward'' function that has &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visibility, returns nothing (indicated by &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;), and has no parameters (indicated by the lack of text between the parentheses &amp;lt;code&amp;gt;()&amp;lt;/code&amp;gt;). The curly brackets, &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;, indicate the function body.&lt;br /&gt;
&lt;br /&gt;
SourceMod plugins are callback-based. In this case, when the plugin was loaded, SourceMod found that it had an &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; ''forward'' function (because of the public visibility mentioned previously), then ran the code within the curly brackets.  If &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; is not specified, SourceMod won't know that there's a function it should run automatically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line tells SourceMod to tell the game to print text to the server console. &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt; is a function defined in SourceMod's standard library. The &amp;lt;code&amp;gt;&amp;amp;quot;Hello, world!&amp;amp;quot;&amp;lt;/code&amp;gt; string is passed as an ''argument'' to &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The semicolon (&amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;) indicates the end of the statement.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;}&amp;lt;/code&amp;gt; on the following line closes the function body and indicates the end of the &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
= Listening to Commands =&lt;br /&gt;
&lt;br /&gt;
Continuing with saying hello to things, we'll now get the server to display a message in response to a player command. In doing so, we'll implement a ''callback'' function ourselves.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action SayHello(int client, int argc) {&lt;br /&gt;
    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save the above code as &amp;lt;code&amp;gt;02_helloclient.sp&amp;lt;/code&amp;gt;, compile, copy, and load. This time you'll only see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[SM] Loaded plugin 02_helloclient.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, connect to your server and type &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; in the client's developer console. You should get:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
] sm_hello&lt;br /&gt;
Hello, (your Steam name)!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also type &amp;lt;code&amp;gt;/hello&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;!hello&amp;lt;/code&amp;gt; in text chat, and get the response back there. SourceMod automatically registers text chat commands with the &amp;lt;code&amp;gt;sm_&amp;lt;/code&amp;gt; prefix stripped.&lt;br /&gt;
&lt;br /&gt;
We'll go a little faster here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the plugin is loaded, {{SourceMod API|file=console|function=RegConsoleCmd}} is called. That function registers a console command &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; — when that command is invoked, it invokes the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; callback function. The function is internal to the plugin, so it does not need to be marked as &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; like &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; is.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Action SayHello(int client, int argc) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; is a user-defined function that follows the ''prototype'' defined by {{SourceMod API|file=console|function=ConCmd}} . A prototype defines the return type and the parameter types of the function. It must follow that prototype exactly; failure to do so will cause the error &amp;amp;quot;function prototypes do not match&amp;amp;quot;, which, to most newer developers, is a familiar compilation error message with words that don't have any sense to them.&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function receives a value named &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, and one named &amp;lt;code&amp;gt;argc&amp;lt;/code&amp;gt;, also of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;; it returns a value of type &amp;lt;code&amp;gt;Action&amp;lt;/code&amp;gt;.  Refer to the link to &amp;lt;code&amp;gt;ConCmd&amp;lt;/code&amp;gt; above for what those parameters mean.&lt;br /&gt;
&lt;br /&gt;
{{Note|If the prototype specifies &amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt; as one of the parameter types, the function can substitute that parameter type with any different non-array parameter.  If the prototype specifies &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;, the function can substitute the parameter with a &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;-derived type.}}&lt;br /&gt;
&lt;br /&gt;
Next line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ReplyToCommand&amp;lt;/code&amp;gt; is a function that tells us to respond to a client (by console or text chat, depending on how the client invoked the command). It takes a minimum of two arguments, the client to respond to, a format string, and optionally a list of format parameters.&lt;br /&gt;
&lt;br /&gt;
In format strings, the &amp;lt;code&amp;gt;%&amp;lt;/code&amp;gt; character is special — it indicates a [[Format_Class_Functions_(SourceMod_Scripting)#Format_Specifiers|''format specifier'']]. The link has more information on what specifiers do, but for now just know that &amp;lt;code&amp;gt;%N&amp;lt;/code&amp;gt; means that it takes the one of the later format parameters (in this case, the second &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; parameter that was passed in to the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function) and outputs the player's name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    return Plugin_Handled;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt; is a keyword that indicates a value that should be given back to the calling function. The calling function is internal to SourceMod in this case. For a command callback, this is an {{SourceMod API|file=core|function=Action}}  enumeration, and we use &amp;lt;code&amp;gt;Plugin_Handled&amp;lt;/code&amp;gt; to tell the server that we acknowledge the command. It'll still work without it, but the server console will report &amp;amp;quot;Unknown command&amp;amp;quot; if you don't return with that value.&lt;br /&gt;
&lt;br /&gt;
= Marking Your Territory =&lt;br /&gt;
&lt;br /&gt;
In this section we will discuss the &amp;lt;code&amp;gt;Plugin&amp;lt;/code&amp;gt; struct, which lets you provide plugin information when displayed in the plugin list.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Entity Properties =&lt;br /&gt;
&lt;br /&gt;
Entity properties are one of the core aspects of game modding.&lt;br /&gt;
&lt;br /&gt;
In this section we will talk about entity send / data properties, and some examples on how to use them.&lt;br /&gt;
&lt;br /&gt;
An ''entity'' is an instance of an object in the world. These include things like players, weapons, grenades, but also abstract things like spawn points, objective areas, and round timers.&lt;br /&gt;
&lt;br /&gt;
Most entities of relevance have ''netprops'' and / or ''datamaps''.  These specific names are Source Engine-specific constructs.&lt;br /&gt;
&lt;br /&gt;
* sendprops / netprops are properties that are sent over the network and intended to ensure the server and connected clients have the correct information.&lt;br /&gt;
* dataprops / datamaps are properties that are saved / restored. (In all honesty, I'm not sure what this means; probably related to either snapshots or game saves.  Someone should edit this with a better explanation, because this is a wiki.)&lt;br /&gt;
&lt;br /&gt;
While they are stored in different ways in the engine, they both correspond to (some, not all) member variables on the entity class that need to be kept track of in some way.&lt;br /&gt;
&lt;br /&gt;
Before we can actually work with them, we need to know which ones exist, so we'll dump them for your game. Open up your server console and type in the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sm_dump_netprops netprops.txt&lt;br /&gt;
sm_dump_datamaps datamaps.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Check the server's game (mod) folder and you should see the &amp;lt;code&amp;gt;netprops.txt&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;datamaps.txt&amp;lt;/code&amp;gt; files.  This will provide you with a list of properties associated with each entity class.&lt;br /&gt;
&lt;br /&gt;
{{Note|Some names are listed as both netprops and dataprops on the same class.  In that situation, using the netprop is preferred, as it will inform the engine that the change needs to be propagated to clients.}}&lt;br /&gt;
&lt;br /&gt;
Here's an example of how to manipulate entities - this plugin zeros out the clip on the active weapon of the player that runs it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_no_clip&amp;quot;, RemoveClip);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action RemoveClip(int client, int argc) {&lt;br /&gt;
    if (client == 0) {&lt;br /&gt;
        // this command is being run by the server console, not an actual player; we can't work with that&lt;br /&gt;
        return Plugin_Handled;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // client is an entity index - we perform a lookup to get the entity assigned to m_hActiveWeapon, if one exists&lt;br /&gt;
    int weapon = GetEntPropEnt(client, Prop_Send, &amp;quot;m_hActiveWeapon&amp;quot;);&lt;br /&gt;
    if (IsValidEntity(weapon)) {&lt;br /&gt;
        // the client has an active weapon - zero out its clip&lt;br /&gt;
        SetEntProp(weapon, Prop_Send, &amp;quot;m_iClip1&amp;quot;, 0);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are many ways to get entities depending on what you are doing.  Some of them are passed directly as a callback argument, others you need to call a function to get one, and others you enumerate over a known allocated space to check.&lt;br /&gt;
&lt;br /&gt;
{{Note|Some properties may not work when set directly.}}&lt;br /&gt;
&lt;br /&gt;
= Timers =&lt;br /&gt;
&lt;br /&gt;
In this section we'll talk about timers and how the &amp;lt;code&amp;gt;any data&amp;lt;/code&amp;gt; parameter works. We should also talk about passing ephemeral data asynchronously (entities and clients).&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedhello&amp;quot;, DelayedHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHello(int client, int argc) {&lt;br /&gt;
    CreateTimer(5.0, DelayedHelloResponse, GetClientSerial(client));&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHelloResponse(Handle timer, int clientserial) {&lt;br /&gt;
    int client = GetClientFromSerial(clientserial);&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;... hello, %N.&amp;quot;, client);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One coding mistake that leads to confusion down the line is directly passing indices of clients or entities through a callback function. '''Don't do this!''' Such indices aren't unique, and there's no guarantee that you'll act on the same entity once the timer is done — the index may be occupied by a different entity or client (or none at all!), and it may have unexpected consequences.&lt;br /&gt;
&lt;br /&gt;
Don't pass client or entity indices.&lt;br /&gt;
&lt;br /&gt;
''Don't pass client or entity indices.''&lt;br /&gt;
&lt;br /&gt;
What you want to do in these cases is convert the index to a reference or serial value before sending it through the timer, then possibly unwrapping it on the other side. The following function pairs handle common cases:&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientSerial}} / {{SourceMod API|file=clients|function=GetClientFromSerial}} returns 0 if the client isn't valid anymore&lt;br /&gt;
* {{SourceMod API|file=halflife|function=EntIndexToEntRef}} / {{SourceMod API|file=halflife|function=EntRefToEntIndex}} returns &amp;lt;code&amp;gt;INVALID_ENT_REFERENCE&amp;lt;/code&amp;gt; if the entity isn't valid; most, if not all SourceMod core functions that accept entity indices also accept entity references, so you may not need to unwrap the reference. Just check with {{SourceMod API|file=entity|function=IsValidEntity}}.&lt;br /&gt;
** If you're testing for entity equality e.g. with the result of {{SourceMod API|file=entity|function=GetEntPropEnt}}, ensure that the reference was converted back to an index, or that both values are references.&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientUserId}} / {{SourceMod API|file=clients|function=GetClientOfUserId}} also returns 0 if the client isn't valid anymore. The values start at 1 and are incremented on player connections and map changes.&lt;br /&gt;
&lt;br /&gt;
= Handles =&lt;br /&gt;
&lt;br /&gt;
A handle is a special type that represents a non-primitive type in SourceMod (any value that isn't a &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt;). Such non-primitive types are implemented as C++ objects, managed by SourceMod, and exposed to SourcePawn plugins indirectly as an integer value.&lt;br /&gt;
&lt;br /&gt;
When you called {{SourceMod API|file=timers|function=CreateTimer}} in the previous section, the function actually returned a timer handle value! We ignored it since we didn't need to worry about storing it (timer handles are a peculiar case), but you generally will want to store handle values in variables.&lt;br /&gt;
&lt;br /&gt;
We'll expand on the timer example above by storing a few more values.  You normally can only pass one value to the timer callback, so we will use a {{SourceMod API|file=datapack|function=DataPack}} to pass more values around.  Take a look at the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedecho&amp;quot;, DelayedEcho);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedEcho(int client, int argc) {&lt;br /&gt;
    char message[64];&lt;br /&gt;
    GetCmdArgString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    // CreateDataTimer instantiates a DataPack instance; normally you would create a handle with &amp;quot;new DataPack()&amp;quot;&lt;br /&gt;
    DataPack pack;&lt;br /&gt;
    CreateDataTimer(5.0, EchoResponse, pack);&lt;br /&gt;
&lt;br /&gt;
    pack.WriteCell(GetClientSerial(client));&lt;br /&gt;
    pack.WriteString(message);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action EchoResponse(Handle timer, DataPack pack) {&lt;br /&gt;
    pack.Reset();&lt;br /&gt;
    int client = GetClientFromSerial(pack.ReadCell());&lt;br /&gt;
    char message[64];&lt;br /&gt;
    pack.ReadString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;Echo! %s&amp;quot;, message);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.  Discuss handle deletion, and why neither the Timer nor DataPack in the example above need to be deleted.}}&lt;br /&gt;
&lt;br /&gt;
For other examples, see the [[Handles (SourceMod Scripting)|Handles page]] on the AlliedModders wiki.&lt;br /&gt;
&lt;br /&gt;
= SDKHooks =&lt;br /&gt;
&lt;br /&gt;
SDKHooks is a first-party SourceMod extension that provides a number of useful entity function hooks.&lt;br /&gt;
&lt;br /&gt;
We'll cover SDKHooks here.  Maybe.  This should probably be shifted over to the quickref.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
If SDKHooks doesn't have a hook on a function you're interested in, you can [[User:Nosoop/Guide/Advanced#Hooking_Game_Functions_.28with_DHooks.29|hook a specific function of your choosing with DHooks]].&lt;br /&gt;
&lt;br /&gt;
= Debugging =&lt;br /&gt;
&lt;br /&gt;
As SourceMod is a third-party framework that is bolted on to a game engine, there's very little debug tooling to test plugins at runtime.&lt;br /&gt;
&lt;br /&gt;
Most, if not all plugin authors use {{SourceMod API|file=console|function=PrintToServer}} to print debug their code of runtime errors.  Some tips:&lt;br /&gt;
&lt;br /&gt;
* Print the ''exact'' values that are being shown if they're relevant.  It narrows down possible issues when you can see that something &amp;quot;is X&amp;quot;, instead of just &amp;quot;is not Y&amp;quot;.&lt;br /&gt;
* Sprinkle in messages at the start of &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;- or &amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt;- statements so you know what code paths are being taken in your plugin.&lt;br /&gt;
&lt;br /&gt;
= Further Reading =&lt;br /&gt;
&lt;br /&gt;
I'm hoping to have further lessons on writing code here, but for now, you can take a look at the [[Introduction to SourcePawn]] and [[Introduction to SourceMod Plugins]] wiki entries.&lt;br /&gt;
&lt;br /&gt;
Information on SourceMod's standard library is available in the [https://sm.alliedmods.net/new-api/ Scripting API Reference].&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11432</id>
		<title>User:Nosoop/Guide/Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11432"/>
		<updated>2023-04-16T10:22:30Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Entity Properties */ Reword some bits&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;At this point you should have a server to test plugins on and a full development environment to write plugins with.&lt;br /&gt;
&lt;br /&gt;
= Hello! =&lt;br /&gt;
&lt;br /&gt;
As is tradition with other programming languages, we'll start with something that outputs &amp;lt;code&amp;gt;Hello, world!&amp;lt;/code&amp;gt; in some form. In this case, you'll install the plugin on your server and load it; the message will be printed in the server console.&lt;br /&gt;
&lt;br /&gt;
Open up your editor, and enter the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save this file as &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt;. SourcePawn scripts always contain the &amp;lt;code&amp;gt;.sp&amp;lt;/code&amp;gt; extension.&lt;br /&gt;
&lt;br /&gt;
Compile your code. Refer to your [[../Development Environments|IDE-specific documentation]] for this.&lt;br /&gt;
&lt;br /&gt;
On a successful compile, you should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
Code size:             2960 bytes&lt;br /&gt;
Data size:             2240 bytes&lt;br /&gt;
Stack/heap size:      16384 bytes&lt;br /&gt;
Total requirements:   21584 bytes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first few lines may be slightly different between SourceMod compiler versions, but as long as you see the four &amp;amp;quot;bytes&amp;amp;quot; lines, you've successfully compiled the plugin, and you should have a &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
If there was an error in compilation, you'll see something like this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
01_hello.sp(4 -- 5) : error 001: expected token: &amp;quot;,&amp;quot;, but found &amp;quot;}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
1 Error.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You'll need to be able to read these sorts of error messages and understand the common ones, because no developer is immune to writing code without any errors all the time.&lt;br /&gt;
&lt;br /&gt;
In this case, the compiler tells us that my &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt; (intentionally made to fail - the code above should compile correctly) has an error around lines 4 and 5, and gives us information about what caused it to not compile the code.&lt;br /&gt;
&lt;br /&gt;
{{Note|Warnings are not errors.&lt;br /&gt;
Learn to differentiate between the two.  If you get a lot of messages when compiling a large plugin, prioritize resolving the errors.  It's possible that some syntax error is causing all sorts of warnings down the line.}}&lt;br /&gt;
&lt;br /&gt;
== Running the Plugin ==&lt;br /&gt;
&lt;br /&gt;
Copy the &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file to your game server's &amp;lt;code&amp;gt;addons/sourcemod/plugins/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
If the server is already running, get to the server console and type &amp;lt;code&amp;gt;sm plugins load 01_hello&amp;lt;/code&amp;gt; to load the plugin. You should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello, world!&lt;br /&gt;
[SM] Loaded plugin 01_hello.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If so, congratulations! You just wrote your first plugin.&lt;br /&gt;
&lt;br /&gt;
== What's in a Plugin ==&lt;br /&gt;
&lt;br /&gt;
Adding text to a file, compiling it, and running the resulting plugin is one thing; it's much more important to understand what the text you're writing actually does.&lt;br /&gt;
&lt;br /&gt;
We'll start from the top:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line is a ''preprocessor directive''. Lines starting with &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; are instructions for the compiler (rather, the preprocessor that examines the code before compilation occurs). In this case, &amp;lt;code&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&amp;lt;/code&amp;gt; tells the preprocessor to include the files that make up SourceMod's standard library.  There are other first- and third-party libraries that you may want to include later on.&lt;br /&gt;
&lt;br /&gt;
Immediately after the line is a blank line. It serves no other purpose other than to visually organize code, but organization is good.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;public void OnPluginStart() {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line defines a function named {{SourceMod API|file=sourcemod|function=OnPluginStart}} in SourceMod (click the link to see the documentation for it). It is a ''forward'' function that has &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visibility, returns nothing (indicated by &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;), and has no parameters (indicated by the lack of text between the parentheses &amp;lt;code&amp;gt;()&amp;lt;/code&amp;gt;). The curly brackets, &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;, indicate the function body.&lt;br /&gt;
&lt;br /&gt;
SourceMod plugins are callback-based. In this case, when the plugin was loaded, SourceMod found that it had an &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; ''forward'' function (because of the public visibility mentioned previously), then ran the code within the curly brackets.  If &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; is not specified, SourceMod won't know that there's a function it should run automatically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line tells SourceMod to tell the game to print text to the server console. &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt; is a function defined in SourceMod's standard library. The &amp;lt;code&amp;gt;&amp;amp;quot;Hello, world!&amp;amp;quot;&amp;lt;/code&amp;gt; string is passed as an ''argument'' to &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The semicolon (&amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;) indicates the end of the statement.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;}&amp;lt;/code&amp;gt; on the following line closes the function body and indicates the end of the &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
= Listening to Commands =&lt;br /&gt;
&lt;br /&gt;
Continuing with saying hello to things, we'll now get the server to display a message in response to a player command. In doing so, we'll implement a ''callback'' function ourselves.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action SayHello(int client, int argc) {&lt;br /&gt;
    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save the above code as &amp;lt;code&amp;gt;02_helloclient.sp&amp;lt;/code&amp;gt;, compile, copy, and load. This time you'll only see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[SM] Loaded plugin 02_helloclient.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, connect to your server and type &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; in the client's developer console. You should get:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
] sm_hello&lt;br /&gt;
Hello, (your Steam name)!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also type &amp;lt;code&amp;gt;/hello&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;!hello&amp;lt;/code&amp;gt; in text chat, and get the response back there. SourceMod automatically registers text chat commands with the &amp;lt;code&amp;gt;sm_&amp;lt;/code&amp;gt; prefix stripped.&lt;br /&gt;
&lt;br /&gt;
We'll go a little faster here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the plugin is loaded, {{SourceMod API|file=console|function=RegConsoleCmd}} is called. That function registers a console command &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; — when that command is invoked, it invokes the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; callback function. The function is internal to the plugin, so it does not need to be marked as &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; like &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; is.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Action SayHello(int client, int argc) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; is a user-defined function that follows the ''prototype'' defined by {{SourceMod API|file=console|function=ConCmd}} . A prototype defines the return type and the parameter types of the function. It must follow that prototype exactly; failure to do so will cause the error &amp;amp;quot;function prototypes do not match&amp;amp;quot;, which, to most newer developers, is a familiar compilation error message with words that don't have any sense to them.&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function receives a value named &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, and one named &amp;lt;code&amp;gt;argc&amp;lt;/code&amp;gt;, also of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;; it returns a value of type &amp;lt;code&amp;gt;Action&amp;lt;/code&amp;gt;.  Refer to the link to &amp;lt;code&amp;gt;ConCmd&amp;lt;/code&amp;gt; above for what those parameters mean.&lt;br /&gt;
&lt;br /&gt;
{{Note|If the prototype specifies &amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt; as one of the parameter types, the function can substitute that parameter type with any different non-array parameter.  If the prototype specifies &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;, the function can substitute the parameter with a &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;-derived type.}}&lt;br /&gt;
&lt;br /&gt;
Next line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ReplyToCommand&amp;lt;/code&amp;gt; is a function that tells us to respond to a client (by console or text chat, depending on how the client invoked the command). It takes a minimum of two arguments, the client to respond to, a format string, and optionally a list of format parameters.&lt;br /&gt;
&lt;br /&gt;
In format strings, the &amp;lt;code&amp;gt;%&amp;lt;/code&amp;gt; character is special — it indicates a [[Format_Class_Functions_(SourceMod_Scripting)#Format_Specifiers|''format specifier'']]. The link has more information on what specifiers do, but for now just know that &amp;lt;code&amp;gt;%N&amp;lt;/code&amp;gt; means that it takes the one of the later format parameters (in this case, the second &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; parameter that was passed in to the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function) and outputs the player's name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    return Plugin_Handled;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt; is a keyword that indicates a value that should be given back to the calling function. The calling function is internal to SourceMod in this case. For a command callback, this is an {{SourceMod API|file=core|function=Action}}  enumeration, and we use &amp;lt;code&amp;gt;Plugin_Handled&amp;lt;/code&amp;gt; to tell the server that we acknowledge the command. It'll still work without it, but the server console will report &amp;amp;quot;Unknown command&amp;amp;quot; if you don't return with that value.&lt;br /&gt;
&lt;br /&gt;
= Marking Your Territory =&lt;br /&gt;
&lt;br /&gt;
In this section we will discuss the &amp;lt;code&amp;gt;Plugin&amp;lt;/code&amp;gt; struct, which lets you provide plugin information when displayed in the plugin list.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Entity Properties =&lt;br /&gt;
&lt;br /&gt;
Entity properties are one of the core aspects of game modding.&lt;br /&gt;
&lt;br /&gt;
In this section we will talk about entity send / data properties, and some examples on how to use them.&lt;br /&gt;
&lt;br /&gt;
An ''entity'' is an instance of an object in the world. These include things like players, weapons, grenades, but also abstract things like spawn points, objective areas, and round timers.&lt;br /&gt;
&lt;br /&gt;
Most entities of relevance have ''netprops'' and / or ''datamaps''.  These specific names are Source Engine-specific constructs.&lt;br /&gt;
&lt;br /&gt;
* sendprops / netprops are properties that are sent over the network and intended to ensure the server and connected clients have the correct information.&lt;br /&gt;
* dataprops / datamaps are properties that are saved / restored. (In all honesty, I'm not sure what this means; probably related to either snapshots or game saves.  Someone should edit this with a better explanation, because this is a wiki.)&lt;br /&gt;
&lt;br /&gt;
While they are stored in different ways in the engine, they both correspond to (some, not all) member variables on the entity class that need to be kept track of in some way.&lt;br /&gt;
&lt;br /&gt;
Before we can actually work with them, we need to know which ones exist, so we'll dump them for your game. Open up your server console and type in the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sm_dump_netprops netprops.txt&lt;br /&gt;
sm_dump_datamaps datamaps.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Check the server's game (mod) folder and you should see the &amp;lt;code&amp;gt;netprops.txt&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;datamaps.txt&amp;lt;/code&amp;gt; files.  This will provide you with a list of properties associated with each entity class.&lt;br /&gt;
&lt;br /&gt;
{{Note|Some names are listed as both netprops and dataprops on the same class.  In that situation, using the netprop is preferred, as it will inform the engine that the change needs to be propagated to clients.}}&lt;br /&gt;
&lt;br /&gt;
Here's an example of how to manipulate entities - this plugin zeros out the clip on the active weapon of the player that runs it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_no_clip&amp;quot;, RemoveClip);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action RemoveClip(int client, int argc) {&lt;br /&gt;
    if (client == 0) {&lt;br /&gt;
        // this command is being run by the server console, not an actual player; we can't work with that&lt;br /&gt;
        return Plugin_Handled;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // client is an entity index - we perform a lookup to get the entity assigned to m_hActiveWeapon, if one exists&lt;br /&gt;
    int weapon = GetEntPropEnt(client, Prop_Send, &amp;quot;m_hActiveWeapon&amp;quot;);&lt;br /&gt;
    if (IsValidEntity(weapon)) {&lt;br /&gt;
        // the client has an active weapon - zero out its clip&lt;br /&gt;
        SetEntProp(weapon, Prop_Send, &amp;quot;m_iClip1&amp;quot;, 0);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are many ways to get entities depending on what you are doing.  Some of them are passed directly as a callback argument, others you need to call a function to get one, and others you enumerate over a known allocated space to check.&lt;br /&gt;
&lt;br /&gt;
{{Note|Some properties may not work when set directly.}}&lt;br /&gt;
&lt;br /&gt;
= Timers =&lt;br /&gt;
&lt;br /&gt;
In this section we'll talk about timers and how the &amp;lt;code&amp;gt;any data&amp;lt;/code&amp;gt; parameter works. We should also talk about passing ephemeral data asynchronously (entities and clients).&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedhello&amp;quot;, DelayedHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHello(int client, int argc) {&lt;br /&gt;
    CreateTimer(5.0, DelayedHelloResponse, GetClientSerial(client));&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHelloResponse(Handle timer, int clientserial) {&lt;br /&gt;
    int client = GetClientFromSerial(clientserial);&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;... hello, %N.&amp;quot;, client);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One coding mistake that leads to confusion down the line is directly passing indices of clients or entities through a callback function. '''Don't do this!''' Such indices aren't unique, and there's no guarantee that you'll act on the same entity once the timer is done — the index may be occupied by a different entity or client (or none at all!), and it may have unexpected consequences.&lt;br /&gt;
&lt;br /&gt;
Don't pass client or entity indices.&lt;br /&gt;
&lt;br /&gt;
''Don't pass client or entity indices.''&lt;br /&gt;
&lt;br /&gt;
What you want to do in these cases is convert the index to a reference or serial value before sending it through the timer, then possibly unwrapping it on the other side. The following function pairs handle common cases:&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientSerial}} / {{SourceMod API|file=clients|function=GetClientFromSerial}} returns 0 if the client isn't valid anymore&lt;br /&gt;
* {{SourceMod API|file=halflife|function=EntIndexToEntRef}} / {{SourceMod API|file=halflife|function=EntRefToEntIndex}} returns &amp;lt;code&amp;gt;INVALID_ENT_REFERENCE&amp;lt;/code&amp;gt; if the entity isn't valid; most, if not all SourceMod core functions that accept entity indices also accept entity references, so you may not need to unwrap the reference. Just check with {{SourceMod API|file=entity|function=IsValidEntity}}.&lt;br /&gt;
** If you're testing for entity equality e.g. with the result of {{SourceMod API|file=entity|function=GetEntPropEnt}}, ensure that the reference was converted back to an index, or that both values are references.&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientUserId}} / {{SourceMod API|file=clients|function=GetClientOfUserId}} also returns 0 if the client isn't valid anymore. The values start at 1 and are incremented on player connections and map changes.&lt;br /&gt;
&lt;br /&gt;
= Handles =&lt;br /&gt;
&lt;br /&gt;
A handle is a special type that represents a non-primitive type in SourceMod (any value that isn't a &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt;). Such non-primitive types are implemented as C++ objects, managed by SourceMod, and exposed to SourcePawn plugins indirectly as an integer value.&lt;br /&gt;
&lt;br /&gt;
When you called {{SourceMod API|file=timers|function=CreateTimer}} in the previous section, the function actually returned a timer handle value! We ignored it since we didn't need to worry about storing it (timer handles are a peculiar case), but you generally will want to store handle values in variables.&lt;br /&gt;
&lt;br /&gt;
We'll expand on the timer example above by storing a few more values.  You normally can only pass one value to the timer callback, so we will use a {{SourceMod API|file=datapack|function=DataPack}} to pass more values around.  Take a look at the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedecho&amp;quot;, DelayedEcho);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedEcho(int client, int argc) {&lt;br /&gt;
    char message[64];&lt;br /&gt;
    GetCmdArgString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    // CreateDataTimer instantiates a DataPack instance; normally you would create a handle with &amp;quot;new DataPack()&amp;quot;&lt;br /&gt;
    DataPack pack;&lt;br /&gt;
    CreateDataTimer(5.0, EchoResponse, pack);&lt;br /&gt;
&lt;br /&gt;
    pack.WriteCell(GetClientSerial(client));&lt;br /&gt;
    pack.WriteString(message);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action EchoResponse(Handle timer, DataPack pack) {&lt;br /&gt;
    pack.Reset();&lt;br /&gt;
    int client = GetClientFromSerial(pack.ReadCell());&lt;br /&gt;
    char message[64];&lt;br /&gt;
    pack.ReadString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;Echo! %s&amp;quot;, message);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.  Discuss handle deletion, and why neither the Timer nor DataPack in the example above need to be deleted.}}&lt;br /&gt;
&lt;br /&gt;
For other examples, see the [[Handles (SourceMod Scripting)|Handles page]] on the AlliedModders wiki.&lt;br /&gt;
&lt;br /&gt;
= SDKHooks =&lt;br /&gt;
&lt;br /&gt;
SDKHooks is a first-party SourceMod extension that provides a number of useful entity function hooks.&lt;br /&gt;
&lt;br /&gt;
We'll cover SDKHooks here.  Maybe.  This should probably be shifted over to the quickref.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
If SDKHooks doesn't have a hook on a function you're interested in, you can [[User:Nosoop/Guide/Advanced#Hooking_Game_Functions_.28with_DHooks.29|hook a specific function of your choosing with DHooks]].&lt;br /&gt;
&lt;br /&gt;
= Debugging =&lt;br /&gt;
&lt;br /&gt;
As SourceMod is a third-party framework that is bolted on to a game engine, there's very little debug tooling to test plugins at runtime.&lt;br /&gt;
&lt;br /&gt;
Most, if not all plugin authors use {{SourceMod API|file=console|function=PrintToServer}} to print debug their code of runtime errors.  Some tips:&lt;br /&gt;
&lt;br /&gt;
* Print the ''exact'' values that are being shown if they're relevant.  It narrows down possible issues when you can see that something &amp;quot;is X&amp;quot;, instead of just &amp;quot;is not Y&amp;quot;.&lt;br /&gt;
* Sprinkle in messages at the start of &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;- or &amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt;- statements so you know what code paths are being taken in your plugin.&lt;br /&gt;
&lt;br /&gt;
= Further Reading =&lt;br /&gt;
&lt;br /&gt;
I'm hoping to have further lessons on writing code here, but for now, you can take a look at the [[Introduction to SourcePawn]] and [[Introduction to SourceMod Plugins]] wiki entries.&lt;br /&gt;
&lt;br /&gt;
Information on SourceMod's standard library is available in the [https://sm.alliedmods.net/new-api/ Scripting API Reference].&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11431</id>
		<title>User:Nosoop/Guide/Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11431"/>
		<updated>2023-04-04T16:35:53Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Picking an IDE */ Raise VSCode due to popularity, remove version number for Sublime Text&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section assumes that you're starting out with nothing besides a desktop computer, an internet connection, and a drive to program some SourceMod plugins. No programming experience; no problem.&lt;br /&gt;
&lt;br /&gt;
This page will walk you through manually installing the dedicated server software for your desired game, installing SourceMod, and selecting a text editor to use for development.&lt;br /&gt;
&lt;br /&gt;
There are a number of third-party tools that can automate most of these steps, but we'll stick to the first-party approach here to avoid abstractions from breaking under you.&lt;br /&gt;
&lt;br /&gt;
If you are using a third-party tool to manage your server installation, refer to the tool's documentation for their instructions, then skip to [[#Installing SourceMod|Installing SourceMod]] to download the scripting toolchain for your desktop operating system.&lt;br /&gt;
&lt;br /&gt;
= Installing the Server =&lt;br /&gt;
&lt;br /&gt;
{{note|&amp;lt;p&amp;gt;While officially unsupported, SourceMod may be loaded on a game client (the game you launch); the server a game client creates is known as a listen server. However, there are many behavioral quirks that can only be reproduced on a listen server, and you likely won't receive any solutions to those issues that aren't &amp;quot;use a dedicated server&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This guide does not provide instructions to load SourceMod on a game client. It's highly recommended to stick to installing SourceMod on dedicated game server instances to ensure that any plugins you write will have the correct behavior.&amp;lt;/p&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
To install the dedicated server software for the game of your choice, we will use &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt;. If a game server provider (GSP) is hosting the server for you, skip this step as your provider has already provided you with an installation; if you are using a self-hosted game server management panel, refer to the instructions for your software of choice to install your game server in place of this step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is Valve's command-line Steam client. It is used to install and update dedicated game servers.&lt;br /&gt;
&lt;br /&gt;
Refer to [https://developer.valvesoftware.com/wiki/SteamCMD the SteamCMD entry] in the Valve Developer Wiki for download instructions. This varies on the operating system you're running the software on; you can either work on your own desktop or have a hosted (physical or virtual) machine off-premises.&lt;br /&gt;
&lt;br /&gt;
Once &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is extracted, you will need to install a game. Continue reading the above wiki page to [https://developer.valvesoftware.com/wiki/SteamCMD#Running_SteamCMD run the application], [https://developer.valvesoftware.com/wiki/SteamCMD#SteamCMD_Login sign in (anonymously)], and [https://developer.valvesoftware.com/wiki/SteamCMD#Downloading_an_App download your game server].&lt;br /&gt;
&lt;br /&gt;
You will need the AppID of the game's dedicated server to install it; note that it is different from the game client AppIDs.  See the below table for that and additional related information for some of the supported games.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Dedicated Server Information&lt;br /&gt;
|-&lt;br /&gt;
! Game&lt;br /&gt;
! AppID&lt;br /&gt;
! Mod Directory&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Day of Defeat: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232290&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;dod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Team Fortress 2&lt;br /&gt;
| &amp;lt;code&amp;gt;232250&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;tf&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232330&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;cstrike&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Global Offensive&lt;br /&gt;
| &amp;lt;code&amp;gt;740&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* As of 1.38.5.2 (2023-02-02), servers running under Linux will need to have a relatively modern libstdc++ installed.  [https://www.mail-archive.com/csgo_servers@list.valvesoftware.com/msg14291.html See this mailing list entry for further details.]&lt;br /&gt;
* [[Introduction to SourceMod Plugins#Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported?|See the current state of Counter-Strike 2 here.]]&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead&lt;br /&gt;
| &amp;lt;code&amp;gt;222840&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* This is the one first-party game that requires a [https://www.metamodsource.net/?go=vdf custom VDF file for Metamod:Source].&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2&lt;br /&gt;
| &amp;lt;code&amp;gt;222860&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Half-Life 2: Deathmatch&lt;br /&gt;
| &amp;lt;code&amp;gt;232370&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;hl2mp&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| No More Room in Hell&lt;br /&gt;
| &amp;lt;code&amp;gt;317670&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;nmrih&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Zombie Panic! Source&lt;br /&gt;
| &amp;lt;code&amp;gt;17505&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;zps&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pirates, Vikings &amp;amp; Knights II&lt;br /&gt;
| &amp;lt;code&amp;gt;17575&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;pvkii&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For post-install server configuration, take a look at the [[../Game Server Configuration|Game Server Configuration]] page.&lt;br /&gt;
&lt;br /&gt;
= Installing Metamod:Source =&lt;br /&gt;
&lt;br /&gt;
Before you can install SourceMod on your server, you must first download and install Metamod:Source. Metamod:Source (MM:S) acts as a middleware for different Source Engine games, providing a unified interface for plugins to operate on the game.&lt;br /&gt;
&lt;br /&gt;
SourceMod itself is an MM:S plugin.&lt;br /&gt;
&lt;br /&gt;
# Download [http://www.metamodsource.net/ Metamod:Source]. In most cases, you want a stable release. Use the download package according to your server's operating system.&lt;br /&gt;
#* If the latest download is unavailable, go down the &amp;amp;quot;Latest 20 Builds&amp;amp;quot; until you get to one that is.&lt;br /&gt;
#* Again, make sure you're downloading the correct package for your server; if you're using a hosted instance, it may not be using the same operating system as your personal desktop.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
#* You may need to extract the archive on, or upload the contents to a remote server.&lt;br /&gt;
#** If you are on Windows, the recommended software to use for extracting Linux (&amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt;) archives is [https://www.7-zip.org/download.html 7-zip]; to upload files remotely via FTP, use [https://winscp.net/eng/index.php WinSCP].&lt;br /&gt;
#** If you are using a GSP, refer to their control panel.  Most provide FTP access, and some also allow for uploads directly via browser.&lt;br /&gt;
# You may want to verify that the installation was successful by starting your server and running &amp;lt;tt&amp;gt;meta version&amp;lt;/tt&amp;gt;.  It should be treated as a known command at this stage.&lt;br /&gt;
#* Most games should work without further configuration, but if you find that MM:S isn't loading, you will want to [https://www.metamodsource.net/?go=vdf generate a custom VDF file].  Known games that require custom VDF files are:&lt;br /&gt;
#** Left 4 Dead 1&lt;br /&gt;
#** Third-party mods using the Source SDK base&lt;br /&gt;
#* Metamod:Source is known to fail to load on CS:GO servers running under Linux by default.  You will want to delete &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to the installation directory, plus read the information in the next bullet point.&lt;br /&gt;
#* If you are using a Linux server you have full control over, read over the [[User:Nosoop/Guide/Game Server Configuration#Platform-specific|Platform-specific setup]] information.&lt;br /&gt;
#* Additional diagnostic information about load failures is available under &amp;lt;tt&amp;gt;metamod-fatal.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Note|On server startup, you may see an error message &amp;lt;tt&amp;gt;Unable to load plugin &amp;quot;addons/metamod/bin/${platform}64/server&amp;quot;&amp;lt;/tt&amp;gt;.  This is normal behavior; the game server will always attempt to load both 32-bit and 64-bit binaries and fail on the one that doesn't match.  If you're sure that you're not running a 64-bit game server instance, you can delete &amp;lt;tt&amp;gt;addons/metamod_x64.vdf&amp;lt;/tt&amp;gt; to only load the 32-bit version, or the other way around.}}&lt;br /&gt;
&lt;br /&gt;
= Installing SourceMod =&lt;br /&gt;
&lt;br /&gt;
The following is mostly lifted from the [[Installing SourceMod]] page.&lt;br /&gt;
&lt;br /&gt;
# Download [https://www.sourcemod.net/ SourceMod]. Same as before; latest available stable release for your server's operating system.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If you plan on creating new plugins, you will also want to download SourceMod for your ''desktop'' operating system and extract the &amp;lt;code&amp;gt;addons/sourcemod/scripting/&amp;lt;/code&amp;gt; folder to a location on your computer.&lt;br /&gt;
&lt;br /&gt;
In the future, you may need to follow [[Upgrading SourceMod|these instructions to upgrade SourceMod]] on your server because of:&lt;br /&gt;
* game updates requiring SourceMod to be rebuilt against a new revision of the Source SDK&lt;br /&gt;
* plugins compiled against newer versions of SourceMod to take advantage of added functionality&lt;br /&gt;
&lt;br /&gt;
= Picking an IDE =&lt;br /&gt;
&lt;br /&gt;
Now that you have the dedicated game server, Metamod:Source, and SourceMod installed, you have most of the tools you need.&lt;br /&gt;
&lt;br /&gt;
If you've never done any programming, you'll need a text editor. It's completely possible to write code in plain old Notepad and invoke the compiler directly, but having a proper development environment makes it much easier to work with code.&lt;br /&gt;
&lt;br /&gt;
The following editors are known to have good support for SourceMod plugins:&lt;br /&gt;
&lt;br /&gt;
* Spider &amp;amp;mdash; recommended when starting out due to it being zero-install; once you are doing more than one-off plugins, move on to one of the non-web text editors&lt;br /&gt;
* Visual Studio Code (VSCode) &amp;amp;mdash; an increasingly popular choice combined with [https://github.com/Sarrus1/sourcepawn-vscode Sarrus's VSCode extension]&lt;br /&gt;
* BasicPawn&lt;br /&gt;
* Notepad++&lt;br /&gt;
* SPEdit&lt;br /&gt;
* Sublime Text&lt;br /&gt;
&lt;br /&gt;
For more details on each editor and, if necessary, how to set it up for writing SourceMod plugins, look at the [[../Development Environments|Development Environments]] section of the guide.&lt;br /&gt;
&lt;br /&gt;
Once you've settled on a development environment, you can start learning how to create plugins &amp;amp;mdash; head over to the [[../Basics|Basics]] section of the guide to get started.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11430</id>
		<title>User:Nosoop/Guide/Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11430"/>
		<updated>2023-04-04T15:58:05Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Entity Properties */ Phrasing!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;At this point you should have a server to test plugins on and a full development environment to write plugins with.&lt;br /&gt;
&lt;br /&gt;
= Hello! =&lt;br /&gt;
&lt;br /&gt;
As is tradition with other programming languages, we'll start with something that outputs &amp;lt;code&amp;gt;Hello, world!&amp;lt;/code&amp;gt; in some form. In this case, you'll install the plugin on your server and load it; the message will be printed in the server console.&lt;br /&gt;
&lt;br /&gt;
Open up your editor, and enter the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save this file as &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt;. SourcePawn scripts always contain the &amp;lt;code&amp;gt;.sp&amp;lt;/code&amp;gt; extension.&lt;br /&gt;
&lt;br /&gt;
Compile your code. Refer to your [[../Development Environments|IDE-specific documentation]] for this.&lt;br /&gt;
&lt;br /&gt;
On a successful compile, you should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
Code size:             2960 bytes&lt;br /&gt;
Data size:             2240 bytes&lt;br /&gt;
Stack/heap size:      16384 bytes&lt;br /&gt;
Total requirements:   21584 bytes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first few lines may be slightly different between SourceMod compiler versions, but as long as you see the four &amp;amp;quot;bytes&amp;amp;quot; lines, you've successfully compiled the plugin, and you should have a &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
If there was an error in compilation, you'll see something like this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
01_hello.sp(4 -- 5) : error 001: expected token: &amp;quot;,&amp;quot;, but found &amp;quot;}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
1 Error.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You'll need to be able to read these sorts of error messages and understand the common ones, because no developer is immune to writing code without any errors all the time.&lt;br /&gt;
&lt;br /&gt;
In this case, the compiler tells us that my &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt; (intentionally made to fail - the code above should compile correctly) has an error around lines 4 and 5, and gives us information about what caused it to not compile the code.&lt;br /&gt;
&lt;br /&gt;
{{Note|Warnings are not errors.&lt;br /&gt;
Learn to differentiate between the two.  If you get a lot of messages when compiling a large plugin, prioritize resolving the errors.  It's possible that some syntax error is causing all sorts of warnings down the line.}}&lt;br /&gt;
&lt;br /&gt;
== Running the Plugin ==&lt;br /&gt;
&lt;br /&gt;
Copy the &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file to your game server's &amp;lt;code&amp;gt;addons/sourcemod/plugins/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
If the server is already running, get to the server console and type &amp;lt;code&amp;gt;sm plugins load 01_hello&amp;lt;/code&amp;gt; to load the plugin. You should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello, world!&lt;br /&gt;
[SM] Loaded plugin 01_hello.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If so, congratulations! You just wrote your first plugin.&lt;br /&gt;
&lt;br /&gt;
== What's in a Plugin ==&lt;br /&gt;
&lt;br /&gt;
Adding text to a file, compiling it, and running the resulting plugin is one thing; it's much more important to understand what the text you're writing actually does.&lt;br /&gt;
&lt;br /&gt;
We'll start from the top:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line is a ''preprocessor directive''. Lines starting with &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; are instructions for the compiler (rather, the preprocessor that examines the code before compilation occurs). In this case, &amp;lt;code&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&amp;lt;/code&amp;gt; tells the preprocessor to include the files that make up SourceMod's standard library.  There are other first- and third-party libraries that you may want to include later on.&lt;br /&gt;
&lt;br /&gt;
Immediately after the line is a blank line. It serves no other purpose other than to visually organize code, but organization is good.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;public void OnPluginStart() {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line defines a function named {{SourceMod API|file=sourcemod|function=OnPluginStart}} in SourceMod (click the link to see the documentation for it). It is a ''forward'' function that has &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visibility, returns nothing (indicated by &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;), and has no parameters (indicated by the lack of text between the parentheses &amp;lt;code&amp;gt;()&amp;lt;/code&amp;gt;). The curly brackets, &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;, indicate the function body.&lt;br /&gt;
&lt;br /&gt;
SourceMod plugins are callback-based. In this case, when the plugin was loaded, SourceMod found that it had an &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; ''forward'' function (because of the public visibility mentioned previously), then ran the code within the curly brackets.  If &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; is not specified, SourceMod won't know that there's a function it should run automatically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line tells SourceMod to tell the game to print text to the server console. &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt; is a function defined in SourceMod's standard library. The &amp;lt;code&amp;gt;&amp;amp;quot;Hello, world!&amp;amp;quot;&amp;lt;/code&amp;gt; string is passed as an ''argument'' to &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The semicolon (&amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;) indicates the end of the statement.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;}&amp;lt;/code&amp;gt; on the following line closes the function body and indicates the end of the &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
= Listening to Commands =&lt;br /&gt;
&lt;br /&gt;
Continuing with saying hello to things, we'll now get the server to display a message in response to a player command. In doing so, we'll implement a ''callback'' function ourselves.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action SayHello(int client, int argc) {&lt;br /&gt;
    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save the above code as &amp;lt;code&amp;gt;02_helloclient.sp&amp;lt;/code&amp;gt;, compile, copy, and load. This time you'll only see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[SM] Loaded plugin 02_helloclient.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, connect to your server and type &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; in the client's developer console. You should get:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
] sm_hello&lt;br /&gt;
Hello, (your Steam name)!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also type &amp;lt;code&amp;gt;/hello&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;!hello&amp;lt;/code&amp;gt; in text chat, and get the response back there. SourceMod automatically registers text chat commands with the &amp;lt;code&amp;gt;sm_&amp;lt;/code&amp;gt; prefix stripped.&lt;br /&gt;
&lt;br /&gt;
We'll go a little faster here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the plugin is loaded, {{SourceMod API|file=console|function=RegConsoleCmd}} is called. That function registers a console command &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; — when that command is invoked, it invokes the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; callback function. The function is internal to the plugin, so it does not need to be marked as &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; like &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; is.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Action SayHello(int client, int argc) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; is a user-defined function that follows the ''prototype'' defined by {{SourceMod API|file=console|function=ConCmd}} . A prototype defines the return type and the parameter types of the function. It must follow that prototype exactly; failure to do so will cause the error &amp;amp;quot;function prototypes do not match&amp;amp;quot;, which, to most newer developers, is a familiar compilation error message with words that don't have any sense to them.&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function receives a value named &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, and one named &amp;lt;code&amp;gt;argc&amp;lt;/code&amp;gt;, also of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;; it returns a value of type &amp;lt;code&amp;gt;Action&amp;lt;/code&amp;gt;.  Refer to the link to &amp;lt;code&amp;gt;ConCmd&amp;lt;/code&amp;gt; above for what those parameters mean.&lt;br /&gt;
&lt;br /&gt;
{{Note|If the prototype specifies &amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt; as one of the parameter types, the function can substitute that parameter type with any different non-array parameter.  If the prototype specifies &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;, the function can substitute the parameter with a &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;-derived type.}}&lt;br /&gt;
&lt;br /&gt;
Next line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ReplyToCommand&amp;lt;/code&amp;gt; is a function that tells us to respond to a client (by console or text chat, depending on how the client invoked the command). It takes a minimum of two arguments, the client to respond to, a format string, and optionally a list of format parameters.&lt;br /&gt;
&lt;br /&gt;
In format strings, the &amp;lt;code&amp;gt;%&amp;lt;/code&amp;gt; character is special — it indicates a [[Format_Class_Functions_(SourceMod_Scripting)#Format_Specifiers|''format specifier'']]. The link has more information on what specifiers do, but for now just know that &amp;lt;code&amp;gt;%N&amp;lt;/code&amp;gt; means that it takes the one of the later format parameters (in this case, the second &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; parameter that was passed in to the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function) and outputs the player's name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    return Plugin_Handled;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt; is a keyword that indicates a value that should be given back to the calling function. The calling function is internal to SourceMod in this case. For a command callback, this is an {{SourceMod API|file=core|function=Action}}  enumeration, and we use &amp;lt;code&amp;gt;Plugin_Handled&amp;lt;/code&amp;gt; to tell the server that we acknowledge the command. It'll still work without it, but the server console will report &amp;amp;quot;Unknown command&amp;amp;quot; if you don't return with that value.&lt;br /&gt;
&lt;br /&gt;
= Marking Your Territory =&lt;br /&gt;
&lt;br /&gt;
In this section we will discuss the &amp;lt;code&amp;gt;Plugin&amp;lt;/code&amp;gt; struct, which lets you provide plugin information when displayed in the plugin list.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Entity Properties =&lt;br /&gt;
&lt;br /&gt;
Entity properties are one of the core aspects of game modding.&lt;br /&gt;
&lt;br /&gt;
In this section we will talk about entity send / data properties, and some examples on how to use them.&lt;br /&gt;
&lt;br /&gt;
An ''entity'' is an instance of an object in the world. These include things like players, weapons, grenades, but also abstract things like spawn points, objective areas, and round timers.&lt;br /&gt;
&lt;br /&gt;
Most entities of relevance have ''netprops'' and / or ''datamaps''.  These specific names are Source Engine-specific constructs.&lt;br /&gt;
&lt;br /&gt;
* sendprops / netprops are properties that are sent over the network.&lt;br /&gt;
* dataprops / datamaps are properties that are saved / restored. (In all honesty, I'm not sure what this means.  Someone should edit this with a better explanation, because this is a wiki.)&lt;br /&gt;
&lt;br /&gt;
While they are stored in different ways in the engine, they both correspond to (some, not all) member variables on the entity class.&lt;br /&gt;
&lt;br /&gt;
Before we can actually work with them, we need to know which ones exist, so we'll dump them for your game. Open up your server console and type in the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sm_dump_netprops netprops.txt&lt;br /&gt;
sm_dump_datamaps datamaps.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Check the server's game (mod) folder and you should see the &amp;lt;code&amp;gt;netprops.txt&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;datamaps.txt&amp;lt;/code&amp;gt; files.  This will provide you with a list of properties associated with each entity class.&lt;br /&gt;
&lt;br /&gt;
{{Note|Some names are listed as both netprops and dataprops on the same class.  In that case, using the netprop is preferred, as it will inform the engine that the change needs to be propagated to clients.}}&lt;br /&gt;
&lt;br /&gt;
Here's an example of how to manipulate entities - this plugin zeros out the clip on the active weapon of the player that runs it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_no_clip&amp;quot;, RemoveClip);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action RemoveClip(int client, int argc) {&lt;br /&gt;
    if (client == 0) {&lt;br /&gt;
        // this command is being run by the server console, not an actual player; we can't work with that&lt;br /&gt;
        return Plugin_Handled;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // client is an entity index - we perform a lookup to get the entity assigned to m_hActiveWeapon, if one exists&lt;br /&gt;
    int weapon = GetEntPropEnt(client, Prop_Send, &amp;quot;m_hActiveWeapon&amp;quot;);&lt;br /&gt;
    if (IsValidEntity(weapon)) {&lt;br /&gt;
        // the client has an active weapon - zero out its clip&lt;br /&gt;
        SetEntProp(weapon, Prop_Send, &amp;quot;m_iClip1&amp;quot;, 0);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are many ways to get entities depending on what you are doing.  Some of them are passed directly as a callback argument, others you need to call a function to get one, and others you enumerate over a known allocated space to check.&lt;br /&gt;
&lt;br /&gt;
{{Note|Some properties may not work when set directly.}}&lt;br /&gt;
&lt;br /&gt;
= Timers =&lt;br /&gt;
&lt;br /&gt;
In this section we'll talk about timers and how the &amp;lt;code&amp;gt;any data&amp;lt;/code&amp;gt; parameter works. We should also talk about passing ephemeral data asynchronously (entities and clients).&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedhello&amp;quot;, DelayedHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHello(int client, int argc) {&lt;br /&gt;
    CreateTimer(5.0, DelayedHelloResponse, GetClientSerial(client));&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHelloResponse(Handle timer, int clientserial) {&lt;br /&gt;
    int client = GetClientFromSerial(clientserial);&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;... hello, %N.&amp;quot;, client);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One coding mistake that leads to confusion down the line is directly passing indices of clients or entities through a callback function. '''Don't do this!''' Such indices aren't unique, and there's no guarantee that you'll act on the same entity once the timer is done — the index may be occupied by a different entity or client (or none at all!), and it may have unexpected consequences.&lt;br /&gt;
&lt;br /&gt;
Don't pass client or entity indices.&lt;br /&gt;
&lt;br /&gt;
''Don't pass client or entity indices.''&lt;br /&gt;
&lt;br /&gt;
What you want to do in these cases is convert the index to a reference or serial value before sending it through the timer, then possibly unwrapping it on the other side. The following function pairs handle common cases:&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientSerial}} / {{SourceMod API|file=clients|function=GetClientFromSerial}} returns 0 if the client isn't valid anymore&lt;br /&gt;
* {{SourceMod API|file=halflife|function=EntIndexToEntRef}} / {{SourceMod API|file=halflife|function=EntRefToEntIndex}} returns &amp;lt;code&amp;gt;INVALID_ENT_REFERENCE&amp;lt;/code&amp;gt; if the entity isn't valid; most, if not all SourceMod core functions that accept entity indices also accept entity references, so you may not need to unwrap the reference. Just check with {{SourceMod API|file=entity|function=IsValidEntity}}.&lt;br /&gt;
** If you're testing for entity equality e.g. with the result of {{SourceMod API|file=entity|function=GetEntPropEnt}}, ensure that the reference was converted back to an index, or that both values are references.&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientUserId}} / {{SourceMod API|file=clients|function=GetClientOfUserId}} also returns 0 if the client isn't valid anymore. The values start at 1 and are incremented on player connections and map changes.&lt;br /&gt;
&lt;br /&gt;
= Handles =&lt;br /&gt;
&lt;br /&gt;
A handle is a special type that represents a non-primitive type in SourceMod (any value that isn't a &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt;). Such non-primitive types are implemented as C++ objects, managed by SourceMod, and exposed to SourcePawn plugins indirectly as an integer value.&lt;br /&gt;
&lt;br /&gt;
When you called {{SourceMod API|file=timers|function=CreateTimer}} in the previous section, the function actually returned a timer handle value! We ignored it since we didn't need to worry about storing it (timer handles are a peculiar case), but you generally will want to store handle values in variables.&lt;br /&gt;
&lt;br /&gt;
We'll expand on the timer example above by storing a few more values.  You normally can only pass one value to the timer callback, so we will use a {{SourceMod API|file=datapack|function=DataPack}} to pass more values around.  Take a look at the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedecho&amp;quot;, DelayedEcho);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedEcho(int client, int argc) {&lt;br /&gt;
    char message[64];&lt;br /&gt;
    GetCmdArgString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    // CreateDataTimer instantiates a DataPack instance; normally you would create a handle with &amp;quot;new DataPack()&amp;quot;&lt;br /&gt;
    DataPack pack;&lt;br /&gt;
    CreateDataTimer(5.0, EchoResponse, pack);&lt;br /&gt;
&lt;br /&gt;
    pack.WriteCell(GetClientSerial(client));&lt;br /&gt;
    pack.WriteString(message);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action EchoResponse(Handle timer, DataPack pack) {&lt;br /&gt;
    pack.Reset();&lt;br /&gt;
    int client = GetClientFromSerial(pack.ReadCell());&lt;br /&gt;
    char message[64];&lt;br /&gt;
    pack.ReadString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;Echo! %s&amp;quot;, message);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.  Discuss handle deletion, and why neither the Timer nor DataPack in the example above need to be deleted.}}&lt;br /&gt;
&lt;br /&gt;
For other examples, see the [[Handles (SourceMod Scripting)|Handles page]] on the AlliedModders wiki.&lt;br /&gt;
&lt;br /&gt;
= SDKHooks =&lt;br /&gt;
&lt;br /&gt;
SDKHooks is a first-party SourceMod extension that provides a number of useful entity function hooks.&lt;br /&gt;
&lt;br /&gt;
We'll cover SDKHooks here.  Maybe.  This should probably be shifted over to the quickref.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
If SDKHooks doesn't have a hook on a function you're interested in, you can [[User:Nosoop/Guide/Advanced#Hooking_Game_Functions_.28with_DHooks.29|hook a specific function of your choosing with DHooks]].&lt;br /&gt;
&lt;br /&gt;
= Debugging =&lt;br /&gt;
&lt;br /&gt;
As SourceMod is a third-party framework that is bolted on to a game engine, there's very little debug tooling to test plugins at runtime.&lt;br /&gt;
&lt;br /&gt;
Most, if not all plugin authors use {{SourceMod API|file=console|function=PrintToServer}} to print debug their code of runtime errors.  Some tips:&lt;br /&gt;
&lt;br /&gt;
* Print the ''exact'' values that are being shown if they're relevant.  It narrows down possible issues when you can see that something &amp;quot;is X&amp;quot;, instead of just &amp;quot;is not Y&amp;quot;.&lt;br /&gt;
* Sprinkle in messages at the start of &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;- or &amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt;- statements so you know what code paths are being taken in your plugin.&lt;br /&gt;
&lt;br /&gt;
= Further Reading =&lt;br /&gt;
&lt;br /&gt;
I'm hoping to have further lessons on writing code here, but for now, you can take a look at the [[Introduction to SourcePawn]] and [[Introduction to SourceMod Plugins]] wiki entries.&lt;br /&gt;
&lt;br /&gt;
Information on SourceMod's standard library is available in the [https://sm.alliedmods.net/new-api/ Scripting API Reference].&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11429</id>
		<title>User:Nosoop/Guide/Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11429"/>
		<updated>2023-04-04T14:37:35Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Entity Properties */ Add example of working with entity properties&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;At this point you should have a server to test plugins on and a full development environment to write plugins with.&lt;br /&gt;
&lt;br /&gt;
= Hello! =&lt;br /&gt;
&lt;br /&gt;
As is tradition with other programming languages, we'll start with something that outputs &amp;lt;code&amp;gt;Hello, world!&amp;lt;/code&amp;gt; in some form. In this case, you'll install the plugin on your server and load it; the message will be printed in the server console.&lt;br /&gt;
&lt;br /&gt;
Open up your editor, and enter the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save this file as &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt;. SourcePawn scripts always contain the &amp;lt;code&amp;gt;.sp&amp;lt;/code&amp;gt; extension.&lt;br /&gt;
&lt;br /&gt;
Compile your code. Refer to your [[../Development Environments|IDE-specific documentation]] for this.&lt;br /&gt;
&lt;br /&gt;
On a successful compile, you should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
Code size:             2960 bytes&lt;br /&gt;
Data size:             2240 bytes&lt;br /&gt;
Stack/heap size:      16384 bytes&lt;br /&gt;
Total requirements:   21584 bytes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first few lines may be slightly different between SourceMod compiler versions, but as long as you see the four &amp;amp;quot;bytes&amp;amp;quot; lines, you've successfully compiled the plugin, and you should have a &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
If there was an error in compilation, you'll see something like this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
01_hello.sp(4 -- 5) : error 001: expected token: &amp;quot;,&amp;quot;, but found &amp;quot;}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
1 Error.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You'll need to be able to read these sorts of error messages and understand the common ones, because no developer is immune to writing code without any errors all the time.&lt;br /&gt;
&lt;br /&gt;
In this case, the compiler tells us that my &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt; (intentionally made to fail - the code above should compile correctly) has an error around lines 4 and 5, and gives us information about what caused it to not compile the code.&lt;br /&gt;
&lt;br /&gt;
{{Note|Warnings are not errors.&lt;br /&gt;
Learn to differentiate between the two.  If you get a lot of messages when compiling a large plugin, prioritize resolving the errors.  It's possible that some syntax error is causing all sorts of warnings down the line.}}&lt;br /&gt;
&lt;br /&gt;
== Running the Plugin ==&lt;br /&gt;
&lt;br /&gt;
Copy the &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file to your game server's &amp;lt;code&amp;gt;addons/sourcemod/plugins/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
If the server is already running, get to the server console and type &amp;lt;code&amp;gt;sm plugins load 01_hello&amp;lt;/code&amp;gt; to load the plugin. You should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello, world!&lt;br /&gt;
[SM] Loaded plugin 01_hello.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If so, congratulations! You just wrote your first plugin.&lt;br /&gt;
&lt;br /&gt;
== What's in a Plugin ==&lt;br /&gt;
&lt;br /&gt;
Adding text to a file, compiling it, and running the resulting plugin is one thing; it's much more important to understand what the text you're writing actually does.&lt;br /&gt;
&lt;br /&gt;
We'll start from the top:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line is a ''preprocessor directive''. Lines starting with &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; are instructions for the compiler (rather, the preprocessor that examines the code before compilation occurs). In this case, &amp;lt;code&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&amp;lt;/code&amp;gt; tells the preprocessor to include the files that make up SourceMod's standard library.  There are other first- and third-party libraries that you may want to include later on.&lt;br /&gt;
&lt;br /&gt;
Immediately after the line is a blank line. It serves no other purpose other than to visually organize code, but organization is good.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;public void OnPluginStart() {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line defines a function named {{SourceMod API|file=sourcemod|function=OnPluginStart}} in SourceMod (click the link to see the documentation for it). It is a ''forward'' function that has &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visibility, returns nothing (indicated by &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;), and has no parameters (indicated by the lack of text between the parentheses &amp;lt;code&amp;gt;()&amp;lt;/code&amp;gt;). The curly brackets, &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;, indicate the function body.&lt;br /&gt;
&lt;br /&gt;
SourceMod plugins are callback-based. In this case, when the plugin was loaded, SourceMod found that it had an &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; ''forward'' function (because of the public visibility mentioned previously), then ran the code within the curly brackets.  If &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; is not specified, SourceMod won't know that there's a function it should run automatically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line tells SourceMod to tell the game to print text to the server console. &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt; is a function defined in SourceMod's standard library. The &amp;lt;code&amp;gt;&amp;amp;quot;Hello, world!&amp;amp;quot;&amp;lt;/code&amp;gt; string is passed as an ''argument'' to &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The semicolon (&amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;) indicates the end of the statement.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;}&amp;lt;/code&amp;gt; on the following line closes the function body and indicates the end of the &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
= Listening to Commands =&lt;br /&gt;
&lt;br /&gt;
Continuing with saying hello to things, we'll now get the server to display a message in response to a player command. In doing so, we'll implement a ''callback'' function ourselves.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action SayHello(int client, int argc) {&lt;br /&gt;
    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save the above code as &amp;lt;code&amp;gt;02_helloclient.sp&amp;lt;/code&amp;gt;, compile, copy, and load. This time you'll only see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[SM] Loaded plugin 02_helloclient.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, connect to your server and type &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; in the client's developer console. You should get:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
] sm_hello&lt;br /&gt;
Hello, (your Steam name)!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also type &amp;lt;code&amp;gt;/hello&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;!hello&amp;lt;/code&amp;gt; in text chat, and get the response back there. SourceMod automatically registers text chat commands with the &amp;lt;code&amp;gt;sm_&amp;lt;/code&amp;gt; prefix stripped.&lt;br /&gt;
&lt;br /&gt;
We'll go a little faster here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the plugin is loaded, {{SourceMod API|file=console|function=RegConsoleCmd}} is called. That function registers a console command &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; — when that command is invoked, it invokes the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; callback function. The function is internal to the plugin, so it does not need to be marked as &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; like &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; is.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Action SayHello(int client, int argc) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; is a user-defined function that follows the ''prototype'' defined by {{SourceMod API|file=console|function=ConCmd}} . A prototype defines the return type and the parameter types of the function. It must follow that prototype exactly; failure to do so will cause the error &amp;amp;quot;function prototypes do not match&amp;amp;quot;, which, to most newer developers, is a familiar compilation error message with words that don't have any sense to them.&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function receives a value named &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, and one named &amp;lt;code&amp;gt;argc&amp;lt;/code&amp;gt;, also of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;; it returns a value of type &amp;lt;code&amp;gt;Action&amp;lt;/code&amp;gt;.  Refer to the link to &amp;lt;code&amp;gt;ConCmd&amp;lt;/code&amp;gt; above for what those parameters mean.&lt;br /&gt;
&lt;br /&gt;
{{Note|If the prototype specifies &amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt; as one of the parameter types, the function can substitute that parameter type with any different non-array parameter.  If the prototype specifies &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;, the function can substitute the parameter with a &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;-derived type.}}&lt;br /&gt;
&lt;br /&gt;
Next line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ReplyToCommand&amp;lt;/code&amp;gt; is a function that tells us to respond to a client (by console or text chat, depending on how the client invoked the command). It takes a minimum of two arguments, the client to respond to, a format string, and optionally a list of format parameters.&lt;br /&gt;
&lt;br /&gt;
In format strings, the &amp;lt;code&amp;gt;%&amp;lt;/code&amp;gt; character is special — it indicates a [[Format_Class_Functions_(SourceMod_Scripting)#Format_Specifiers|''format specifier'']]. The link has more information on what specifiers do, but for now just know that &amp;lt;code&amp;gt;%N&amp;lt;/code&amp;gt; means that it takes the one of the later format parameters (in this case, the second &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; parameter that was passed in to the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function) and outputs the player's name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    return Plugin_Handled;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt; is a keyword that indicates a value that should be given back to the calling function. The calling function is internal to SourceMod in this case. For a command callback, this is an {{SourceMod API|file=core|function=Action}}  enumeration, and we use &amp;lt;code&amp;gt;Plugin_Handled&amp;lt;/code&amp;gt; to tell the server that we acknowledge the command. It'll still work without it, but the server console will report &amp;amp;quot;Unknown command&amp;amp;quot; if you don't return with that value.&lt;br /&gt;
&lt;br /&gt;
= Marking Your Territory =&lt;br /&gt;
&lt;br /&gt;
In this section we will discuss the &amp;lt;code&amp;gt;Plugin&amp;lt;/code&amp;gt; struct, which lets you provide plugin information when displayed in the plugin list.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Entity Properties =&lt;br /&gt;
&lt;br /&gt;
Entity properties are one of the core aspects of game modding.&lt;br /&gt;
&lt;br /&gt;
In this section we will talk about entity send / data properties, and some examples on how to use them.&lt;br /&gt;
&lt;br /&gt;
An ''entity'' is an instance of an object in the world. These include things like players, weapons, grenades, but also abstract things like spawn points, objective areas, and round timers.&lt;br /&gt;
&lt;br /&gt;
Most entities of relevance have ''netprops'' and / or ''datamaps''.  These specific names are Source Engine-specific constructs.&lt;br /&gt;
&lt;br /&gt;
* sendprops / netprops are properties that are sent over the network.&lt;br /&gt;
* dataprops / datamaps are properties that are saved / restored. (In all honesty, I'm not sure what this means.  Someone should edit this with a better explanation, because this is a wiki.)&lt;br /&gt;
&lt;br /&gt;
While they are stored in different ways in the engine, they both correspond to (some, not all) member variables on the entity class.&lt;br /&gt;
&lt;br /&gt;
Before we can actually work with them, we need to know which ones exist, so we'll dump them for your game. Open up your server console and type in the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sm_dump_netprops netprops.txt&lt;br /&gt;
sm_dump_datamaps datamaps.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Check the server's game (mod) folder and you should see the &amp;lt;code&amp;gt;netprops.txt&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;datamaps.txt&amp;lt;/code&amp;gt;.  This will provide you with a list of properties associated with each entity class.&lt;br /&gt;
&lt;br /&gt;
{{Note|Some names refer to both netprops and dataprops.  In that case, using the netprop is preferred, as it will inform the engine that the change needs to be propagated to clients.}}&lt;br /&gt;
&lt;br /&gt;
Here's an example of how to manipulate entities - this plugin zeros out the clip on the active weapon of the player that runs it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_no_clip&amp;quot;, RemoveClip);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action RemoveClip(int client, int argc) {&lt;br /&gt;
    if (client == 0) {&lt;br /&gt;
        // this command is being run by the server console, not an actual player; we can't work with that&lt;br /&gt;
        return Plugin_Handled;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // client is an entity index - we perform a lookup to get the entity assigned to m_hActiveWeapon, if one exists&lt;br /&gt;
    int weapon = GetEntPropEnt(client, Prop_Send, &amp;quot;m_hActiveWeapon&amp;quot;);&lt;br /&gt;
    if (IsValidEntity(weapon)) {&lt;br /&gt;
        // the client has an active weapon - zero out its clip&lt;br /&gt;
        SetEntProp(weapon, Prop_Send, &amp;quot;m_iClip1&amp;quot;, 0);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are many ways to get entities depending on what you are doing.  Some of them are passed directly as a callback argument, others you need to call a function to get one, and others you enumerate over a known allocated space to check.&lt;br /&gt;
&lt;br /&gt;
{{Note|Some properties may not work when set directly.}}&lt;br /&gt;
&lt;br /&gt;
= Timers =&lt;br /&gt;
&lt;br /&gt;
In this section we'll talk about timers and how the &amp;lt;code&amp;gt;any data&amp;lt;/code&amp;gt; parameter works. We should also talk about passing ephemeral data asynchronously (entities and clients).&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedhello&amp;quot;, DelayedHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHello(int client, int argc) {&lt;br /&gt;
    CreateTimer(5.0, DelayedHelloResponse, GetClientSerial(client));&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHelloResponse(Handle timer, int clientserial) {&lt;br /&gt;
    int client = GetClientFromSerial(clientserial);&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;... hello, %N.&amp;quot;, client);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One coding mistake that leads to confusion down the line is directly passing indices of clients or entities through a callback function. '''Don't do this!''' Such indices aren't unique, and there's no guarantee that you'll act on the same entity once the timer is done — the index may be occupied by a different entity or client (or none at all!), and it may have unexpected consequences.&lt;br /&gt;
&lt;br /&gt;
Don't pass client or entity indices.&lt;br /&gt;
&lt;br /&gt;
''Don't pass client or entity indices.''&lt;br /&gt;
&lt;br /&gt;
What you want to do in these cases is convert the index to a reference or serial value before sending it through the timer, then possibly unwrapping it on the other side. The following function pairs handle common cases:&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientSerial}} / {{SourceMod API|file=clients|function=GetClientFromSerial}} returns 0 if the client isn't valid anymore&lt;br /&gt;
* {{SourceMod API|file=halflife|function=EntIndexToEntRef}} / {{SourceMod API|file=halflife|function=EntRefToEntIndex}} returns &amp;lt;code&amp;gt;INVALID_ENT_REFERENCE&amp;lt;/code&amp;gt; if the entity isn't valid; most, if not all SourceMod core functions that accept entity indices also accept entity references, so you may not need to unwrap the reference. Just check with {{SourceMod API|file=entity|function=IsValidEntity}}.&lt;br /&gt;
** If you're testing for entity equality e.g. with the result of {{SourceMod API|file=entity|function=GetEntPropEnt}}, ensure that the reference was converted back to an index, or that both values are references.&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientUserId}} / {{SourceMod API|file=clients|function=GetClientOfUserId}} also returns 0 if the client isn't valid anymore. The values start at 1 and are incremented on player connections and map changes.&lt;br /&gt;
&lt;br /&gt;
= Handles =&lt;br /&gt;
&lt;br /&gt;
A handle is a special type that represents a non-primitive type in SourceMod (any value that isn't a &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt;). Such non-primitive types are implemented as C++ objects, managed by SourceMod, and exposed to SourcePawn plugins indirectly as an integer value.&lt;br /&gt;
&lt;br /&gt;
When you called {{SourceMod API|file=timers|function=CreateTimer}} in the previous section, the function actually returned a timer handle value! We ignored it since we didn't need to worry about storing it (timer handles are a peculiar case), but you generally will want to store handle values in variables.&lt;br /&gt;
&lt;br /&gt;
We'll expand on the timer example above by storing a few more values.  You normally can only pass one value to the timer callback, so we will use a {{SourceMod API|file=datapack|function=DataPack}} to pass more values around.  Take a look at the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedecho&amp;quot;, DelayedEcho);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedEcho(int client, int argc) {&lt;br /&gt;
    char message[64];&lt;br /&gt;
    GetCmdArgString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    // CreateDataTimer instantiates a DataPack instance; normally you would create a handle with &amp;quot;new DataPack()&amp;quot;&lt;br /&gt;
    DataPack pack;&lt;br /&gt;
    CreateDataTimer(5.0, EchoResponse, pack);&lt;br /&gt;
&lt;br /&gt;
    pack.WriteCell(GetClientSerial(client));&lt;br /&gt;
    pack.WriteString(message);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action EchoResponse(Handle timer, DataPack pack) {&lt;br /&gt;
    pack.Reset();&lt;br /&gt;
    int client = GetClientFromSerial(pack.ReadCell());&lt;br /&gt;
    char message[64];&lt;br /&gt;
    pack.ReadString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;Echo! %s&amp;quot;, message);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.  Discuss handle deletion, and why neither the Timer nor DataPack in the example above need to be deleted.}}&lt;br /&gt;
&lt;br /&gt;
For other examples, see the [[Handles (SourceMod Scripting)|Handles page]] on the AlliedModders wiki.&lt;br /&gt;
&lt;br /&gt;
= SDKHooks =&lt;br /&gt;
&lt;br /&gt;
SDKHooks is a first-party SourceMod extension that provides a number of useful entity function hooks.&lt;br /&gt;
&lt;br /&gt;
We'll cover SDKHooks here.  Maybe.  This should probably be shifted over to the quickref.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
If SDKHooks doesn't have a hook on a function you're interested in, you can [[User:Nosoop/Guide/Advanced#Hooking_Game_Functions_.28with_DHooks.29|hook a specific function of your choosing with DHooks]].&lt;br /&gt;
&lt;br /&gt;
= Debugging =&lt;br /&gt;
&lt;br /&gt;
As SourceMod is a third-party framework that is bolted on to a game engine, there's very little debug tooling to test plugins at runtime.&lt;br /&gt;
&lt;br /&gt;
Most, if not all plugin authors use {{SourceMod API|file=console|function=PrintToServer}} to print debug their code of runtime errors.  Some tips:&lt;br /&gt;
&lt;br /&gt;
* Print the ''exact'' values that are being shown if they're relevant.  It narrows down possible issues when you can see that something &amp;quot;is X&amp;quot;, instead of just &amp;quot;is not Y&amp;quot;.&lt;br /&gt;
* Sprinkle in messages at the start of &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;- or &amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt;- statements so you know what code paths are being taken in your plugin.&lt;br /&gt;
&lt;br /&gt;
= Further Reading =&lt;br /&gt;
&lt;br /&gt;
I'm hoping to have further lessons on writing code here, but for now, you can take a look at the [[Introduction to SourcePawn]] and [[Introduction to SourceMod Plugins]] wiki entries.&lt;br /&gt;
&lt;br /&gt;
Information on SourceMod's standard library is available in the [https://sm.alliedmods.net/new-api/ Scripting API Reference].&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11428</id>
		<title>User:Nosoop/Guide/Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11428"/>
		<updated>2023-04-04T14:17:58Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Entity Properties */ Describe what an entity is&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;At this point you should have a server to test plugins on and a full development environment to write plugins with.&lt;br /&gt;
&lt;br /&gt;
= Hello! =&lt;br /&gt;
&lt;br /&gt;
As is tradition with other programming languages, we'll start with something that outputs &amp;lt;code&amp;gt;Hello, world!&amp;lt;/code&amp;gt; in some form. In this case, you'll install the plugin on your server and load it; the message will be printed in the server console.&lt;br /&gt;
&lt;br /&gt;
Open up your editor, and enter the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save this file as &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt;. SourcePawn scripts always contain the &amp;lt;code&amp;gt;.sp&amp;lt;/code&amp;gt; extension.&lt;br /&gt;
&lt;br /&gt;
Compile your code. Refer to your [[../Development Environments|IDE-specific documentation]] for this.&lt;br /&gt;
&lt;br /&gt;
On a successful compile, you should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
Code size:             2960 bytes&lt;br /&gt;
Data size:             2240 bytes&lt;br /&gt;
Stack/heap size:      16384 bytes&lt;br /&gt;
Total requirements:   21584 bytes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first few lines may be slightly different between SourceMod compiler versions, but as long as you see the four &amp;amp;quot;bytes&amp;amp;quot; lines, you've successfully compiled the plugin, and you should have a &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
If there was an error in compilation, you'll see something like this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
01_hello.sp(4 -- 5) : error 001: expected token: &amp;quot;,&amp;quot;, but found &amp;quot;}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
1 Error.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You'll need to be able to read these sorts of error messages and understand the common ones, because no developer is immune to writing code without any errors all the time.&lt;br /&gt;
&lt;br /&gt;
In this case, the compiler tells us that my &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt; (intentionally made to fail - the code above should compile correctly) has an error around lines 4 and 5, and gives us information about what caused it to not compile the code.&lt;br /&gt;
&lt;br /&gt;
{{Note|Warnings are not errors.&lt;br /&gt;
Learn to differentiate between the two.  If you get a lot of messages when compiling a large plugin, prioritize resolving the errors.  It's possible that some syntax error is causing all sorts of warnings down the line.}}&lt;br /&gt;
&lt;br /&gt;
== Running the Plugin ==&lt;br /&gt;
&lt;br /&gt;
Copy the &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file to your game server's &amp;lt;code&amp;gt;addons/sourcemod/plugins/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
If the server is already running, get to the server console and type &amp;lt;code&amp;gt;sm plugins load 01_hello&amp;lt;/code&amp;gt; to load the plugin. You should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello, world!&lt;br /&gt;
[SM] Loaded plugin 01_hello.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If so, congratulations! You just wrote your first plugin.&lt;br /&gt;
&lt;br /&gt;
== What's in a Plugin ==&lt;br /&gt;
&lt;br /&gt;
Adding text to a file, compiling it, and running the resulting plugin is one thing; it's much more important to understand what the text you're writing actually does.&lt;br /&gt;
&lt;br /&gt;
We'll start from the top:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line is a ''preprocessor directive''. Lines starting with &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; are instructions for the compiler (rather, the preprocessor that examines the code before compilation occurs). In this case, &amp;lt;code&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&amp;lt;/code&amp;gt; tells the preprocessor to include the files that make up SourceMod's standard library.  There are other first- and third-party libraries that you may want to include later on.&lt;br /&gt;
&lt;br /&gt;
Immediately after the line is a blank line. It serves no other purpose other than to visually organize code, but organization is good.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;public void OnPluginStart() {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line defines a function named {{SourceMod API|file=sourcemod|function=OnPluginStart}} in SourceMod (click the link to see the documentation for it). It is a ''forward'' function that has &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visibility, returns nothing (indicated by &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;), and has no parameters (indicated by the lack of text between the parentheses &amp;lt;code&amp;gt;()&amp;lt;/code&amp;gt;). The curly brackets, &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;, indicate the function body.&lt;br /&gt;
&lt;br /&gt;
SourceMod plugins are callback-based. In this case, when the plugin was loaded, SourceMod found that it had an &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; ''forward'' function (because of the public visibility mentioned previously), then ran the code within the curly brackets.  If &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; is not specified, SourceMod won't know that there's a function it should run automatically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line tells SourceMod to tell the game to print text to the server console. &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt; is a function defined in SourceMod's standard library. The &amp;lt;code&amp;gt;&amp;amp;quot;Hello, world!&amp;amp;quot;&amp;lt;/code&amp;gt; string is passed as an ''argument'' to &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The semicolon (&amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;) indicates the end of the statement.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;}&amp;lt;/code&amp;gt; on the following line closes the function body and indicates the end of the &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
= Listening to Commands =&lt;br /&gt;
&lt;br /&gt;
Continuing with saying hello to things, we'll now get the server to display a message in response to a player command. In doing so, we'll implement a ''callback'' function ourselves.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action SayHello(int client, int argc) {&lt;br /&gt;
    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save the above code as &amp;lt;code&amp;gt;02_helloclient.sp&amp;lt;/code&amp;gt;, compile, copy, and load. This time you'll only see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[SM] Loaded plugin 02_helloclient.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, connect to your server and type &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; in the client's developer console. You should get:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
] sm_hello&lt;br /&gt;
Hello, (your Steam name)!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also type &amp;lt;code&amp;gt;/hello&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;!hello&amp;lt;/code&amp;gt; in text chat, and get the response back there. SourceMod automatically registers text chat commands with the &amp;lt;code&amp;gt;sm_&amp;lt;/code&amp;gt; prefix stripped.&lt;br /&gt;
&lt;br /&gt;
We'll go a little faster here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the plugin is loaded, {{SourceMod API|file=console|function=RegConsoleCmd}} is called. That function registers a console command &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; — when that command is invoked, it invokes the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; callback function. The function is internal to the plugin, so it does not need to be marked as &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; like &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; is.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Action SayHello(int client, int argc) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; is a user-defined function that follows the ''prototype'' defined by {{SourceMod API|file=console|function=ConCmd}} . A prototype defines the return type and the parameter types of the function. It must follow that prototype exactly; failure to do so will cause the error &amp;amp;quot;function prototypes do not match&amp;amp;quot;, which, to most newer developers, is a familiar compilation error message with words that don't have any sense to them.&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function receives a value named &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, and one named &amp;lt;code&amp;gt;argc&amp;lt;/code&amp;gt;, also of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;; it returns a value of type &amp;lt;code&amp;gt;Action&amp;lt;/code&amp;gt;.  Refer to the link to &amp;lt;code&amp;gt;ConCmd&amp;lt;/code&amp;gt; above for what those parameters mean.&lt;br /&gt;
&lt;br /&gt;
{{Note|If the prototype specifies &amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt; as one of the parameter types, the function can substitute that parameter type with any different non-array parameter.  If the prototype specifies &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;, the function can substitute the parameter with a &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;-derived type.}}&lt;br /&gt;
&lt;br /&gt;
Next line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ReplyToCommand&amp;lt;/code&amp;gt; is a function that tells us to respond to a client (by console or text chat, depending on how the client invoked the command). It takes a minimum of two arguments, the client to respond to, a format string, and optionally a list of format parameters.&lt;br /&gt;
&lt;br /&gt;
In format strings, the &amp;lt;code&amp;gt;%&amp;lt;/code&amp;gt; character is special — it indicates a [[Format_Class_Functions_(SourceMod_Scripting)#Format_Specifiers|''format specifier'']]. The link has more information on what specifiers do, but for now just know that &amp;lt;code&amp;gt;%N&amp;lt;/code&amp;gt; means that it takes the one of the later format parameters (in this case, the second &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; parameter that was passed in to the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function) and outputs the player's name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    return Plugin_Handled;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt; is a keyword that indicates a value that should be given back to the calling function. The calling function is internal to SourceMod in this case. For a command callback, this is an {{SourceMod API|file=core|function=Action}}  enumeration, and we use &amp;lt;code&amp;gt;Plugin_Handled&amp;lt;/code&amp;gt; to tell the server that we acknowledge the command. It'll still work without it, but the server console will report &amp;amp;quot;Unknown command&amp;amp;quot; if you don't return with that value.&lt;br /&gt;
&lt;br /&gt;
= Marking Your Territory =&lt;br /&gt;
&lt;br /&gt;
In this section we will discuss the &amp;lt;code&amp;gt;Plugin&amp;lt;/code&amp;gt; struct, which lets you provide plugin information when displayed in the plugin list.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Entity Properties =&lt;br /&gt;
&lt;br /&gt;
Entity properties are one of the core aspects of game modding.&lt;br /&gt;
&lt;br /&gt;
In this section we will talk about entity send / data properties, and some examples on how to use them.&lt;br /&gt;
&lt;br /&gt;
An ''entity'' is an instance of an object in the world. These include things like players, weapons, grenades, but also abstract things like spawn points, objective areas, and round timers.&lt;br /&gt;
&lt;br /&gt;
Most entities of relevance have ''netprops'' and / or ''datamaps''.  These specific names are Source Engine-specific constructs.&lt;br /&gt;
&lt;br /&gt;
* sendprops / netprops are properties that are sent over the network.&lt;br /&gt;
* dataprops / datamaps are properties that are saved / restored. (In all honesty, I'm not sure what this means.  Someone should edit this with a better explanation, because this is a wiki.)&lt;br /&gt;
&lt;br /&gt;
While they are stored in different ways in the engine, they both correspond to (some, not all) member variables on the entity class.&lt;br /&gt;
&lt;br /&gt;
Before we can actually work with them, we need to know which ones exist, so we'll dump them for your game. Open up your server console and type in the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sm_dump_netprops netprops.txt&lt;br /&gt;
sm_dump_datamaps datamaps.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Check the server's game (mod) folder and you should see the &amp;lt;code&amp;gt;netprops.txt&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;datamaps.txt&amp;lt;/code&amp;gt;.  This will provide you with a list of properties associated with each entity class.&lt;br /&gt;
&lt;br /&gt;
{{Note|Some names refer to both netprops and dataprops.  In that case, using the netprop is preferred, as it will inform the engine that the change needs to be propagated to clients.}}&lt;br /&gt;
&lt;br /&gt;
= Timers =&lt;br /&gt;
&lt;br /&gt;
In this section we'll talk about timers and how the &amp;lt;code&amp;gt;any data&amp;lt;/code&amp;gt; parameter works. We should also talk about passing ephemeral data asynchronously (entities and clients).&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedhello&amp;quot;, DelayedHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHello(int client, int argc) {&lt;br /&gt;
    CreateTimer(5.0, DelayedHelloResponse, GetClientSerial(client));&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHelloResponse(Handle timer, int clientserial) {&lt;br /&gt;
    int client = GetClientFromSerial(clientserial);&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;... hello, %N.&amp;quot;, client);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One coding mistake that leads to confusion down the line is directly passing indices of clients or entities through a callback function. '''Don't do this!''' Such indices aren't unique, and there's no guarantee that you'll act on the same entity once the timer is done — the index may be occupied by a different entity or client (or none at all!), and it may have unexpected consequences.&lt;br /&gt;
&lt;br /&gt;
Don't pass client or entity indices.&lt;br /&gt;
&lt;br /&gt;
''Don't pass client or entity indices.''&lt;br /&gt;
&lt;br /&gt;
What you want to do in these cases is convert the index to a reference or serial value before sending it through the timer, then possibly unwrapping it on the other side. The following function pairs handle common cases:&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientSerial}} / {{SourceMod API|file=clients|function=GetClientFromSerial}} returns 0 if the client isn't valid anymore&lt;br /&gt;
* {{SourceMod API|file=halflife|function=EntIndexToEntRef}} / {{SourceMod API|file=halflife|function=EntRefToEntIndex}} returns &amp;lt;code&amp;gt;INVALID_ENT_REFERENCE&amp;lt;/code&amp;gt; if the entity isn't valid; most, if not all SourceMod core functions that accept entity indices also accept entity references, so you may not need to unwrap the reference. Just check with {{SourceMod API|file=entity|function=IsValidEntity}}.&lt;br /&gt;
** If you're testing for entity equality e.g. with the result of {{SourceMod API|file=entity|function=GetEntPropEnt}}, ensure that the reference was converted back to an index, or that both values are references.&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientUserId}} / {{SourceMod API|file=clients|function=GetClientOfUserId}} also returns 0 if the client isn't valid anymore. The values start at 1 and are incremented on player connections and map changes.&lt;br /&gt;
&lt;br /&gt;
= Handles =&lt;br /&gt;
&lt;br /&gt;
A handle is a special type that represents a non-primitive type in SourceMod (any value that isn't a &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt;). Such non-primitive types are implemented as C++ objects, managed by SourceMod, and exposed to SourcePawn plugins indirectly as an integer value.&lt;br /&gt;
&lt;br /&gt;
When you called {{SourceMod API|file=timers|function=CreateTimer}} in the previous section, the function actually returned a timer handle value! We ignored it since we didn't need to worry about storing it (timer handles are a peculiar case), but you generally will want to store handle values in variables.&lt;br /&gt;
&lt;br /&gt;
We'll expand on the timer example above by storing a few more values.  You normally can only pass one value to the timer callback, so we will use a {{SourceMod API|file=datapack|function=DataPack}} to pass more values around.  Take a look at the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedecho&amp;quot;, DelayedEcho);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedEcho(int client, int argc) {&lt;br /&gt;
    char message[64];&lt;br /&gt;
    GetCmdArgString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    // CreateDataTimer instantiates a DataPack instance; normally you would create a handle with &amp;quot;new DataPack()&amp;quot;&lt;br /&gt;
    DataPack pack;&lt;br /&gt;
    CreateDataTimer(5.0, EchoResponse, pack);&lt;br /&gt;
&lt;br /&gt;
    pack.WriteCell(GetClientSerial(client));&lt;br /&gt;
    pack.WriteString(message);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action EchoResponse(Handle timer, DataPack pack) {&lt;br /&gt;
    pack.Reset();&lt;br /&gt;
    int client = GetClientFromSerial(pack.ReadCell());&lt;br /&gt;
    char message[64];&lt;br /&gt;
    pack.ReadString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;Echo! %s&amp;quot;, message);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.  Discuss handle deletion, and why neither the Timer nor DataPack in the example above need to be deleted.}}&lt;br /&gt;
&lt;br /&gt;
For other examples, see the [[Handles (SourceMod Scripting)|Handles page]] on the AlliedModders wiki.&lt;br /&gt;
&lt;br /&gt;
= SDKHooks =&lt;br /&gt;
&lt;br /&gt;
SDKHooks is a first-party SourceMod extension that provides a number of useful entity function hooks.&lt;br /&gt;
&lt;br /&gt;
We'll cover SDKHooks here.  Maybe.  This should probably be shifted over to the quickref.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
If SDKHooks doesn't have a hook on a function you're interested in, you can [[User:Nosoop/Guide/Advanced#Hooking_Game_Functions_.28with_DHooks.29|hook a specific function of your choosing with DHooks]].&lt;br /&gt;
&lt;br /&gt;
= Debugging =&lt;br /&gt;
&lt;br /&gt;
As SourceMod is a third-party framework that is bolted on to a game engine, there's very little debug tooling to test plugins at runtime.&lt;br /&gt;
&lt;br /&gt;
Most, if not all plugin authors use {{SourceMod API|file=console|function=PrintToServer}} to print debug their code of runtime errors.  Some tips:&lt;br /&gt;
&lt;br /&gt;
* Print the ''exact'' values that are being shown if they're relevant.  It narrows down possible issues when you can see that something &amp;quot;is X&amp;quot;, instead of just &amp;quot;is not Y&amp;quot;.&lt;br /&gt;
* Sprinkle in messages at the start of &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;- or &amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt;- statements so you know what code paths are being taken in your plugin.&lt;br /&gt;
&lt;br /&gt;
= Further Reading =&lt;br /&gt;
&lt;br /&gt;
I'm hoping to have further lessons on writing code here, but for now, you can take a look at the [[Introduction to SourcePawn]] and [[Introduction to SourceMod Plugins]] wiki entries.&lt;br /&gt;
&lt;br /&gt;
Information on SourceMod's standard library is available in the [https://sm.alliedmods.net/new-api/ Scripting API Reference].&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11427</id>
		<title>User:Nosoop/Guide/Basics</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Basics&amp;diff=11427"/>
		<updated>2023-04-04T10:52:10Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* What's in a Plugin */ Add notes to include, clarify 'forward' functions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;At this point you should have a server to test plugins on and a full development environment to write plugins with.&lt;br /&gt;
&lt;br /&gt;
= Hello! =&lt;br /&gt;
&lt;br /&gt;
As is tradition with other programming languages, we'll start with something that outputs &amp;lt;code&amp;gt;Hello, world!&amp;lt;/code&amp;gt; in some form. In this case, you'll install the plugin on your server and load it; the message will be printed in the server console.&lt;br /&gt;
&lt;br /&gt;
Open up your editor, and enter the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save this file as &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt;. SourcePawn scripts always contain the &amp;lt;code&amp;gt;.sp&amp;lt;/code&amp;gt; extension.&lt;br /&gt;
&lt;br /&gt;
Compile your code. Refer to your [[../Development Environments|IDE-specific documentation]] for this.&lt;br /&gt;
&lt;br /&gt;
On a successful compile, you should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
Code size:             2960 bytes&lt;br /&gt;
Data size:             2240 bytes&lt;br /&gt;
Stack/heap size:      16384 bytes&lt;br /&gt;
Total requirements:   21584 bytes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first few lines may be slightly different between SourceMod compiler versions, but as long as you see the four &amp;amp;quot;bytes&amp;amp;quot; lines, you've successfully compiled the plugin, and you should have a &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
If there was an error in compilation, you'll see something like this instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SourcePawn Compiler 1.9&lt;br /&gt;
Copyright (c) 1997-2006 ITB CompuPhase&lt;br /&gt;
Copyright (c) 2004-2017 AlliedModders LLC&lt;br /&gt;
&lt;br /&gt;
01_hello.sp(4 -- 5) : error 001: expected token: &amp;quot;,&amp;quot;, but found &amp;quot;}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
1 Error.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You'll need to be able to read these sorts of error messages and understand the common ones, because no developer is immune to writing code without any errors all the time.&lt;br /&gt;
&lt;br /&gt;
In this case, the compiler tells us that my &amp;lt;code&amp;gt;01_hello.sp&amp;lt;/code&amp;gt; (intentionally made to fail - the code above should compile correctly) has an error around lines 4 and 5, and gives us information about what caused it to not compile the code.&lt;br /&gt;
&lt;br /&gt;
{{Note|Warnings are not errors.&lt;br /&gt;
Learn to differentiate between the two.  If you get a lot of messages when compiling a large plugin, prioritize resolving the errors.  It's possible that some syntax error is causing all sorts of warnings down the line.}}&lt;br /&gt;
&lt;br /&gt;
== Running the Plugin ==&lt;br /&gt;
&lt;br /&gt;
Copy the &amp;lt;code&amp;gt;01_hello.smx&amp;lt;/code&amp;gt; file to your game server's &amp;lt;code&amp;gt;addons/sourcemod/plugins/&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
If the server is already running, get to the server console and type &amp;lt;code&amp;gt;sm plugins load 01_hello&amp;lt;/code&amp;gt; to load the plugin. You should see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hello, world!&lt;br /&gt;
[SM] Loaded plugin 01_hello.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If so, congratulations! You just wrote your first plugin.&lt;br /&gt;
&lt;br /&gt;
== What's in a Plugin ==&lt;br /&gt;
&lt;br /&gt;
Adding text to a file, compiling it, and running the resulting plugin is one thing; it's much more important to understand what the text you're writing actually does.&lt;br /&gt;
&lt;br /&gt;
We'll start from the top:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line is a ''preprocessor directive''. Lines starting with &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt; are instructions for the compiler (rather, the preprocessor that examines the code before compilation occurs). In this case, &amp;lt;code&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&amp;lt;/code&amp;gt; tells the preprocessor to include the files that make up SourceMod's standard library.  There are other first- and third-party libraries that you may want to include later on.&lt;br /&gt;
&lt;br /&gt;
Immediately after the line is a blank line. It serves no other purpose other than to visually organize code, but organization is good.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;public void OnPluginStart() {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line defines a function named {{SourceMod API|file=sourcemod|function=OnPluginStart}} in SourceMod (click the link to see the documentation for it). It is a ''forward'' function that has &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; visibility, returns nothing (indicated by &amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt;), and has no parameters (indicated by the lack of text between the parentheses &amp;lt;code&amp;gt;()&amp;lt;/code&amp;gt;). The curly brackets, &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;, indicate the function body.&lt;br /&gt;
&lt;br /&gt;
SourceMod plugins are callback-based. In this case, when the plugin was loaded, SourceMod found that it had an &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; ''forward'' function (because of the public visibility mentioned previously), then ran the code within the curly brackets.  If &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; is not specified, SourceMod won't know that there's a function it should run automatically.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    PrintToServer(&amp;amp;quot;Hello, world!&amp;amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This line tells SourceMod to tell the game to print text to the server console. &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt; is a function defined in SourceMod's standard library. The &amp;lt;code&amp;gt;&amp;amp;quot;Hello, world!&amp;amp;quot;&amp;lt;/code&amp;gt; string is passed as an ''argument'' to &amp;lt;code&amp;gt;PrintToServer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The semicolon (&amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;) indicates the end of the statement.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;}&amp;lt;/code&amp;gt; on the following line closes the function body and indicates the end of the &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
= Listening to Commands =&lt;br /&gt;
&lt;br /&gt;
Continuing with saying hello to things, we'll now get the server to display a message in response to a player command. In doing so, we'll implement a ''callback'' function ourselves.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;#include &amp;amp;lt;sourcemod&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action SayHello(int client, int argc) {&lt;br /&gt;
    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Save the above code as &amp;lt;code&amp;gt;02_helloclient.sp&amp;lt;/code&amp;gt;, compile, copy, and load. This time you'll only see the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[SM] Loaded plugin 02_helloclient.smx successfully.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, connect to your server and type &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; in the client's developer console. You should get:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
] sm_hello&lt;br /&gt;
Hello, (your Steam name)!&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also type &amp;lt;code&amp;gt;/hello&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;!hello&amp;lt;/code&amp;gt; in text chat, and get the response back there. SourceMod automatically registers text chat commands with the &amp;lt;code&amp;gt;sm_&amp;lt;/code&amp;gt; prefix stripped.&lt;br /&gt;
&lt;br /&gt;
We'll go a little faster here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    RegConsoleCmd(&amp;amp;quot;sm_hello&amp;amp;quot;, SayHello);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the plugin is loaded, {{SourceMod API|file=console|function=RegConsoleCmd}} is called. That function registers a console command &amp;lt;code&amp;gt;sm_hello&amp;lt;/code&amp;gt; — when that command is invoked, it invokes the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; callback function. The function is internal to the plugin, so it does not need to be marked as &amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt; like &amp;lt;code&amp;gt;OnPluginStart&amp;lt;/code&amp;gt; is.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Action SayHello(int client, int argc) {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; is a user-defined function that follows the ''prototype'' defined by {{SourceMod API|file=console|function=ConCmd}} . A prototype defines the return type and the parameter types of the function. It must follow that prototype exactly; failure to do so will cause the error &amp;amp;quot;function prototypes do not match&amp;amp;quot;, which, to most newer developers, is a familiar compilation error message with words that don't have any sense to them.&lt;br /&gt;
&lt;br /&gt;
In this case, the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function receives a value named &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, and one named &amp;lt;code&amp;gt;argc&amp;lt;/code&amp;gt;, also of type &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;; it returns a value of type &amp;lt;code&amp;gt;Action&amp;lt;/code&amp;gt;.  Refer to the link to &amp;lt;code&amp;gt;ConCmd&amp;lt;/code&amp;gt; above for what those parameters mean.&lt;br /&gt;
&lt;br /&gt;
{{Note|If the prototype specifies &amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt; as one of the parameter types, the function can substitute that parameter type with any different non-array parameter.  If the prototype specifies &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;, the function can substitute the parameter with a &amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;-derived type.}}&lt;br /&gt;
&lt;br /&gt;
Next line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    ReplyToCommand(client, &amp;amp;quot;Hello, %N!&amp;amp;quot;, client);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ReplyToCommand&amp;lt;/code&amp;gt; is a function that tells us to respond to a client (by console or text chat, depending on how the client invoked the command). It takes a minimum of two arguments, the client to respond to, a format string, and optionally a list of format parameters.&lt;br /&gt;
&lt;br /&gt;
In format strings, the &amp;lt;code&amp;gt;%&amp;lt;/code&amp;gt; character is special — it indicates a [[Format_Class_Functions_(SourceMod_Scripting)#Format_Specifiers|''format specifier'']]. The link has more information on what specifiers do, but for now just know that &amp;lt;code&amp;gt;%N&amp;lt;/code&amp;gt; means that it takes the one of the later format parameters (in this case, the second &amp;lt;code&amp;gt;client&amp;lt;/code&amp;gt; parameter that was passed in to the &amp;lt;code&amp;gt;SayHello&amp;lt;/code&amp;gt; function) and outputs the player's name.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;    return Plugin_Handled;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt; is a keyword that indicates a value that should be given back to the calling function. The calling function is internal to SourceMod in this case. For a command callback, this is an {{SourceMod API|file=core|function=Action}}  enumeration, and we use &amp;lt;code&amp;gt;Plugin_Handled&amp;lt;/code&amp;gt; to tell the server that we acknowledge the command. It'll still work without it, but the server console will report &amp;amp;quot;Unknown command&amp;amp;quot; if you don't return with that value.&lt;br /&gt;
&lt;br /&gt;
= Marking Your Territory =&lt;br /&gt;
&lt;br /&gt;
In this section we will discuss the &amp;lt;code&amp;gt;Plugin&amp;lt;/code&amp;gt; struct, which lets you provide plugin information when displayed in the plugin list.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
= Entity Properties =&lt;br /&gt;
&lt;br /&gt;
Entity properties are one of the core aspects of game modding.&lt;br /&gt;
&lt;br /&gt;
In this section we will talk about entity send / data properties, and some examples on how to use them.&lt;br /&gt;
&lt;br /&gt;
Most entities of relevance have ''netprops'' and / or ''datamaps''.  These specific names are Source Engine-specific constructs.&lt;br /&gt;
&lt;br /&gt;
* sendprops / netprops are properties that are sent over the network.&lt;br /&gt;
* dataprops / datamaps are properties that are saved / restored. (In all honesty, I'm not sure what this means.  Someone should edit this with a better explanation, because this is a wiki.)&lt;br /&gt;
&lt;br /&gt;
While they are stored in different ways in the engine, they both correspond to (some, not all) member variables on the entity class.&lt;br /&gt;
&lt;br /&gt;
Before we can actually work with them, we need to know which ones exist, so we'll dump them for your game. Open up your server console and type in the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sm_dump_netprops netprops.txt&lt;br /&gt;
sm_dump_datamaps datamaps.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Check the server's game (mod) folder and you should see the &amp;lt;code&amp;gt;netprops.txt&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;datamaps.txt&amp;lt;/code&amp;gt;.  This will provide you with a list of properties associated with each entity class.&lt;br /&gt;
&lt;br /&gt;
{{Note|Some names refer to both netprops and dataprops.  In that case, using the netprop is preferred, as it will inform the engine that the change needs to be propagated to clients.}}&lt;br /&gt;
&lt;br /&gt;
= Timers =&lt;br /&gt;
&lt;br /&gt;
In this section we'll talk about timers and how the &amp;lt;code&amp;gt;any data&amp;lt;/code&amp;gt; parameter works. We should also talk about passing ephemeral data asynchronously (entities and clients).&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedhello&amp;quot;, DelayedHello);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHello(int client, int argc) {&lt;br /&gt;
    CreateTimer(5.0, DelayedHelloResponse, GetClientSerial(client));&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedHelloResponse(Handle timer, int clientserial) {&lt;br /&gt;
    int client = GetClientFromSerial(clientserial);&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;... hello, %N.&amp;quot;, client);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
One coding mistake that leads to confusion down the line is directly passing indices of clients or entities through a callback function. '''Don't do this!''' Such indices aren't unique, and there's no guarantee that you'll act on the same entity once the timer is done — the index may be occupied by a different entity or client (or none at all!), and it may have unexpected consequences.&lt;br /&gt;
&lt;br /&gt;
Don't pass client or entity indices.&lt;br /&gt;
&lt;br /&gt;
''Don't pass client or entity indices.''&lt;br /&gt;
&lt;br /&gt;
What you want to do in these cases is convert the index to a reference or serial value before sending it through the timer, then possibly unwrapping it on the other side. The following function pairs handle common cases:&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientSerial}} / {{SourceMod API|file=clients|function=GetClientFromSerial}} returns 0 if the client isn't valid anymore&lt;br /&gt;
* {{SourceMod API|file=halflife|function=EntIndexToEntRef}} / {{SourceMod API|file=halflife|function=EntRefToEntIndex}} returns &amp;lt;code&amp;gt;INVALID_ENT_REFERENCE&amp;lt;/code&amp;gt; if the entity isn't valid; most, if not all SourceMod core functions that accept entity indices also accept entity references, so you may not need to unwrap the reference. Just check with {{SourceMod API|file=entity|function=IsValidEntity}}.&lt;br /&gt;
** If you're testing for entity equality e.g. with the result of {{SourceMod API|file=entity|function=GetEntPropEnt}}, ensure that the reference was converted back to an index, or that both values are references.&lt;br /&gt;
* {{SourceMod API|file=clients|function=GetClientUserId}} / {{SourceMod API|file=clients|function=GetClientOfUserId}} also returns 0 if the client isn't valid anymore. The values start at 1 and are incremented on player connections and map changes.&lt;br /&gt;
&lt;br /&gt;
= Handles =&lt;br /&gt;
&lt;br /&gt;
A handle is a special type that represents a non-primitive type in SourceMod (any value that isn't a &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt;). Such non-primitive types are implemented as C++ objects, managed by SourceMod, and exposed to SourcePawn plugins indirectly as an integer value.&lt;br /&gt;
&lt;br /&gt;
When you called {{SourceMod API|file=timers|function=CreateTimer}} in the previous section, the function actually returned a timer handle value! We ignored it since we didn't need to worry about storing it (timer handles are a peculiar case), but you generally will want to store handle values in variables.&lt;br /&gt;
&lt;br /&gt;
We'll expand on the timer example above by storing a few more values.  You normally can only pass one value to the timer callback, so we will use a {{SourceMod API|file=datapack|function=DataPack}} to pass more values around.  Take a look at the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart() {&lt;br /&gt;
    RegConsoleCmd(&amp;quot;sm_delayedecho&amp;quot;, DelayedEcho);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action DelayedEcho(int client, int argc) {&lt;br /&gt;
    char message[64];&lt;br /&gt;
    GetCmdArgString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    // CreateDataTimer instantiates a DataPack instance; normally you would create a handle with &amp;quot;new DataPack()&amp;quot;&lt;br /&gt;
    DataPack pack;&lt;br /&gt;
    CreateDataTimer(5.0, EchoResponse, pack);&lt;br /&gt;
&lt;br /&gt;
    pack.WriteCell(GetClientSerial(client));&lt;br /&gt;
    pack.WriteString(message);&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Action EchoResponse(Handle timer, DataPack pack) {&lt;br /&gt;
    pack.Reset();&lt;br /&gt;
    int client = GetClientFromSerial(pack.ReadCell());&lt;br /&gt;
    char message[64];&lt;br /&gt;
    pack.ReadString(message, sizeof(message));&lt;br /&gt;
&lt;br /&gt;
    if (client) {&lt;br /&gt;
        PrintToChat(client, &amp;quot;Echo! %s&amp;quot;, message);&lt;br /&gt;
    }&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.  Discuss handle deletion, and why neither the Timer nor DataPack in the example above need to be deleted.}}&lt;br /&gt;
&lt;br /&gt;
For other examples, see the [[Handles (SourceMod Scripting)|Handles page]] on the AlliedModders wiki.&lt;br /&gt;
&lt;br /&gt;
= SDKHooks =&lt;br /&gt;
&lt;br /&gt;
SDKHooks is a first-party SourceMod extension that provides a number of useful entity function hooks.&lt;br /&gt;
&lt;br /&gt;
We'll cover SDKHooks here.  Maybe.  This should probably be shifted over to the quickref.&lt;br /&gt;
&lt;br /&gt;
{{Note|This section is a work-in-progress.}}&lt;br /&gt;
&lt;br /&gt;
If SDKHooks doesn't have a hook on a function you're interested in, you can [[User:Nosoop/Guide/Advanced#Hooking_Game_Functions_.28with_DHooks.29|hook a specific function of your choosing with DHooks]].&lt;br /&gt;
&lt;br /&gt;
= Debugging =&lt;br /&gt;
&lt;br /&gt;
As SourceMod is a third-party framework that is bolted on to a game engine, there's very little debug tooling to test plugins at runtime.&lt;br /&gt;
&lt;br /&gt;
Most, if not all plugin authors use {{SourceMod API|file=console|function=PrintToServer}} to print debug their code of runtime errors.  Some tips:&lt;br /&gt;
&lt;br /&gt;
* Print the ''exact'' values that are being shown if they're relevant.  It narrows down possible issues when you can see that something &amp;quot;is X&amp;quot;, instead of just &amp;quot;is not Y&amp;quot;.&lt;br /&gt;
* Sprinkle in messages at the start of &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;- or &amp;lt;code&amp;gt;else&amp;lt;/code&amp;gt;- statements so you know what code paths are being taken in your plugin.&lt;br /&gt;
&lt;br /&gt;
= Further Reading =&lt;br /&gt;
&lt;br /&gt;
I'm hoping to have further lessons on writing code here, but for now, you can take a look at the [[Introduction to SourcePawn]] and [[Introduction to SourceMod Plugins]] wiki entries.&lt;br /&gt;
&lt;br /&gt;
Information on SourceMod's standard library is available in the [https://sm.alliedmods.net/new-api/ Scripting API Reference].&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11426</id>
		<title>User:Nosoop/Guide/Game Server Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Game_Server_Configuration&amp;diff=11426"/>
		<updated>2023-04-02T18:08:34Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* SourceMod extension not loading */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Source Engine games often differ in configuration; here are some basic suggestions on how to set them up for either testing or production use.&lt;br /&gt;
&lt;br /&gt;
= General =&lt;br /&gt;
&lt;br /&gt;
The following section(s) apply to most, if not all games.&lt;br /&gt;
&lt;br /&gt;
== Fast Downloads ==&lt;br /&gt;
&lt;br /&gt;
The Source Engine normally provides downloads over the same channel as gameplay, which is rather slow.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;quot;Fast&amp;amp;quot; downloads are downloads served out-of-band over HTTP, and as such you will need to have a web (HTTP) server up and running to take advantage of this functionality.  This is highly recommended if you are running a server with any amount of custom content that a player needs to download (models, sounds, maps).&lt;br /&gt;
&lt;br /&gt;
If you're using a game server provider, you may already have access to a web server for fast download purposes; check with your provider to confirm.&lt;br /&gt;
&lt;br /&gt;
Examples of web servers include: [https://www.nginx.com/ nginx], [https://caddyserver.com/ Caddy], [https://httpd.apache.org/ Apache], [https://www.rejetto.com/hfs/ HFS], and [https://en.wikipedia.org/wiki/Comparison_of_web_server_software many others] (and many more not included in that list).&lt;br /&gt;
&lt;br /&gt;
Once you have an HTTP server running, configure &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_downloadurl &amp;amp;quot;http://{your_server_location}/{path}&amp;amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The URL must be quoted, as &amp;lt;tt&amp;gt;//&amp;lt;/tt&amp;gt; is treated as the start of a comment and if left unquoted, the rest of the line will be ignored.  Do not include a trailing slash &amp;amp;mdash; the game client adds one when making the request; web servers are not guaranteed to collapse double slashes in the path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;{path}&amp;lt;/tt&amp;gt; should be the path on your server that would translate to the root of your game server.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a file &amp;lt;tt&amp;gt;sound/my_server/fart.mp3&amp;lt;/tt&amp;gt; and an &amp;lt;tt&amp;gt;sv_downloadurl&amp;lt;/tt&amp;gt; value of &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;, the client will request &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;http://example.com/gameserverdownloads/sound/my_server/fart.mp3&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt; (and its BZip2-compressed equivalent).&lt;br /&gt;
&lt;br /&gt;
You will need to also copy the files from the game server to the web server.&lt;br /&gt;
&lt;br /&gt;
== SourceMod extension not loading ==&lt;br /&gt;
&lt;br /&gt;
By default, if no plugin depends on an extension, it won't be loaded automatically, nor will it show up in &amp;lt;tt&amp;gt;sm exts list&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;tt&amp;gt;sm exts load ${extension}&amp;lt;/tt&amp;gt; if you'd like to test if it loads and to see if it fails, or add an &amp;lt;tt&amp;gt;${extension}.autoload&amp;lt;/tt&amp;gt; file (empty or not) in the extensions directory if you always want it to load.&lt;br /&gt;
&lt;br /&gt;
= Platform-specific =&lt;br /&gt;
&lt;br /&gt;
== Linux extension failing to load on outdated &amp;lt;tt&amp;gt;GLIBCXX_*&amp;lt;/tt&amp;gt; version ==&lt;br /&gt;
&lt;br /&gt;
Various Source Engine games (Counter Strike: Source, Day of Defeat: Source, Counter Strike: Global Offensive, third-party games using the Source SDK modding system, possibly others) bundle standard libraries that are older than what current operating systems ship with, but newer than those that Valve ships as a baseline.&lt;br /&gt;
&lt;br /&gt;
Software that depends on new versions of libraries will fail to load.  This includes Metamod:Source, SourceMod, and other native code / plugins / extension.&lt;br /&gt;
&lt;br /&gt;
You can choose to do one of the following:&lt;br /&gt;
&lt;br /&gt;
* Remove any existing copies of &amp;lt;tt&amp;gt;bin/libstdc++.so.6&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to your game install directory (not the root of the filesytem); this will let the game load the system libraries.&lt;br /&gt;
** If you are on a 64-bit system, continue to the [[#64-bit_Linux_systems_and_32-bit_executables|next section]] to ensure the system's 32-bit libraries are actually available after removing the Valve-bundled copies.&lt;br /&gt;
* If your operating system is also dated, you will need rebuild the extension using an older build environment, or upgrade to a newer one.  If you plan on recompiling the extension, the [https://github.com/ValveSoftware/steam-runtime Steam Runtime SDK] is considered the baseline of support.&lt;br /&gt;
&lt;br /&gt;
== 64-bit Linux systems and 32-bit executables ==&lt;br /&gt;
&lt;br /&gt;
[https://sporks.space/2022/02/27/win32-is-the-stable-linux-userland-abi-and-the-consequences/ Unlike Windows], 64-bit Linux systems are not guaranteed to ship with full compatibility for 32-bit executables by default.&lt;br /&gt;
&lt;br /&gt;
Depending on your distribution, you will need to run one of the following commands as root to install the required packages / libraries:&lt;br /&gt;
&lt;br /&gt;
* Debian / Ubuntu: &amp;lt;tt&amp;gt;apt install gcc-multilib&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Arch: &amp;lt;tt&amp;gt;pacman -S lib32-gcc-libs&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Fedora: &amp;lt;tt&amp;gt;yum -y install glibc.i686&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Game Specific =&lt;br /&gt;
&lt;br /&gt;
== Team Fortress 2 ==&lt;br /&gt;
&lt;br /&gt;
The [https://wiki.teamfortress.com/wiki/Dedicated_server_configuration Dedicated server configuration] section on the Team Fortress 2 Official Wiki provides general configuration instructions.  Depending on the platform you're working on, you may also be interested in the sections for [https://wiki.teamfortress.com/wiki/Linux_dedicated_server Linux] and [https://wiki.teamfortress.com/wiki/Windows_dedicated_server Windows].&lt;br /&gt;
&lt;br /&gt;
=== Mann vs. Machine ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;tt&amp;gt;tf_mvm_min_players_to_start&amp;lt;/tt&amp;gt; to 1 to only require one player to ready up and start the mission.&lt;br /&gt;
&lt;br /&gt;
=== Steam Datagram Relay ===&lt;br /&gt;
&lt;br /&gt;
The Steam Datagram Relay routes both server and client connections through the Steam network, hiding the IP address of each from the other.&lt;br /&gt;
&lt;br /&gt;
Pass &amp;lt;tt&amp;gt;-enablefakeip&amp;lt;/tt&amp;gt; in the server's launch options to enable.  The server will then report &amp;quot;FakeIP allocation succeeded&amp;quot; at the end of startup; use that IP address / port combination in your game client to connect to the server.  This allocation will change on every server startup.&lt;br /&gt;
&lt;br /&gt;
=== Games that aren't ===&lt;br /&gt;
&lt;br /&gt;
Non-exhaustive list of Source Engine class-based shooters with a cartoon-like visual style based on the art of Dean Cornwell, J. C. Leyendecker, and Norman Rockwell, that aren't [https://store.steampowered.com/app/440/Team_Fortress_2/ Team Fortress 2]:&lt;br /&gt;
&lt;br /&gt;
* Team Fortress 2 Classic&lt;br /&gt;
* Open Fortress&lt;br /&gt;
&lt;br /&gt;
If you're developing plugins and asking questions about one of those games, please specifically name them.  These games are not guaranteed to behave the same as &amp;quot;retail&amp;quot; Team Fortress 2, and solutions that work for retail aren't guaranteed to work on third-party mods.&lt;br /&gt;
&lt;br /&gt;
== Counter-Strike: Global Offensive ==&lt;br /&gt;
&lt;br /&gt;
The [https://developer.valvesoftware.com/wiki/Counter-Strike:_Global_Offensive_Dedicated_Servers#Advanced_Configuration Advanced Configuration] section on the Valve Developer Wiki describes server configuration unique to CS:GO. It's different from most other mods.&lt;br /&gt;
&lt;br /&gt;
=== Responsive server console when hibernating ===&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;sv_hibernate_ms&amp;lt;/code&amp;gt; to 0 to make the server console more responsive when no players are online.&lt;br /&gt;
&lt;br /&gt;
== Left 4 Dead 2 ==&lt;br /&gt;
&lt;br /&gt;
=== Disabling lobby system ===&lt;br /&gt;
&lt;br /&gt;
While developing plugins, you generally don't want players being connected through Steam's lobby system.  Add the following to &amp;lt;code&amp;gt;server.cfg&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sv_allow_lobby_connect_only &amp;quot;0&amp;quot;;&lt;br /&gt;
sv_password &amp;quot;password_to_connect_with&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Virtual Server Configuration =&lt;br /&gt;
&lt;br /&gt;
As a developer, you may need to test on multiple platforms. To avoid having another physical machine to work on, you can use virtualization to run an operating system on your desktop.&lt;br /&gt;
&lt;br /&gt;
== Virtualbox ==&lt;br /&gt;
&lt;br /&gt;
=== Networking ===&lt;br /&gt;
&lt;br /&gt;
==== Network Address Translation ====&lt;br /&gt;
&lt;br /&gt;
With NAT plus port forwarding, the minimum would be to forward UDP from one of the host's loopback IP addresses to the server port on the VM's address.  Forwarding TCP isn't necessary unless you are interested in using the RCON protocol.&lt;br /&gt;
&lt;br /&gt;
For example, given a virtual machine with an IP address of &amp;lt;tt&amp;gt;10.0.2.15&amp;lt;/tt&amp;gt; and the server listening on port 27015, you should configure NAT as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt; (host) &amp;amp;rarr; &amp;lt;tt&amp;gt;10.0.2.15:27015&amp;lt;/tt&amp;gt; (guest)&lt;br /&gt;
&lt;br /&gt;
You can then connect to the server from the host OS by connecting to &amp;lt;tt&amp;gt;127.0.2.15:27015&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Any loopback IP address on the host portion is acceptable to use (that is, any address starting with &amp;lt;tt&amp;gt;127.*.*.*&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Host-Only Adapter ====&lt;br /&gt;
&lt;br /&gt;
Enable the Host-Only Adapter on your VM and statically assign the address to be in the same network as your host operating system's adapter. This allows you to connect to the server without any additional networking complexities.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11425</id>
		<title>User:Nosoop/Guide/Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11425"/>
		<updated>2023-04-01T15:19:00Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Installing Metamod:Source */ Enforce spacing consistency between list identifiers&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section assumes that you're starting out with nothing besides a desktop computer, an internet connection, and a drive to program some SourceMod plugins. No programming experience; no problem.&lt;br /&gt;
&lt;br /&gt;
This page will walk you through manually installing the dedicated server software for your desired game, installing SourceMod, and selecting a text editor to use for development.&lt;br /&gt;
&lt;br /&gt;
There are a number of third-party tools that can automate most of these steps, but we'll stick to the first-party approach here to avoid abstractions from breaking under you.&lt;br /&gt;
&lt;br /&gt;
If you are using a third-party tool to manage your server installation, refer to the tool's documentation for their instructions, then skip to [[#Installing SourceMod|Installing SourceMod]] to download the scripting toolchain for your desktop operating system.&lt;br /&gt;
&lt;br /&gt;
= Installing the Server =&lt;br /&gt;
&lt;br /&gt;
{{note|&amp;lt;p&amp;gt;While officially unsupported, SourceMod may be loaded on a game client (the game you launch); the server a game client creates is known as a listen server. However, there are many behavioral quirks that can only be reproduced on a listen server, and you likely won't receive any solutions to those issues that aren't &amp;quot;use a dedicated server&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This guide does not provide instructions to load SourceMod on a game client. It's highly recommended to stick to installing SourceMod on dedicated game server instances to ensure that any plugins you write will have the correct behavior.&amp;lt;/p&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
To install the dedicated server software for the game of your choice, we will use &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt;. If a game server provider (GSP) is hosting the server for you, skip this step as your provider has already provided you with an installation; if you are using a self-hosted game server management panel, refer to the instructions for your software of choice to install your game server in place of this step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is Valve's command-line Steam client. It is used to install and update dedicated game servers.&lt;br /&gt;
&lt;br /&gt;
Refer to [https://developer.valvesoftware.com/wiki/SteamCMD the SteamCMD entry] in the Valve Developer Wiki for download instructions. This varies on the operating system you're running the software on; you can either work on your own desktop or have a hosted (physical or virtual) machine off-premises.&lt;br /&gt;
&lt;br /&gt;
Once &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is extracted, you will need to install a game. Continue reading the above wiki page to [https://developer.valvesoftware.com/wiki/SteamCMD#Running_SteamCMD run the application], [https://developer.valvesoftware.com/wiki/SteamCMD#SteamCMD_Login sign in (anonymously)], and [https://developer.valvesoftware.com/wiki/SteamCMD#Downloading_an_App download your game server].&lt;br /&gt;
&lt;br /&gt;
You will need the AppID of the game's dedicated server to install it; note that it is different from the game client AppIDs.  See the below table for that and additional related information for some of the supported games.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Dedicated Server Information&lt;br /&gt;
|-&lt;br /&gt;
! Game&lt;br /&gt;
! AppID&lt;br /&gt;
! Mod Directory&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Day of Defeat: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232290&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;dod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Team Fortress 2&lt;br /&gt;
| &amp;lt;code&amp;gt;232250&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;tf&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232330&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;cstrike&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Global Offensive&lt;br /&gt;
| &amp;lt;code&amp;gt;740&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* As of 1.38.5.2 (2023-02-02), servers running under Linux will need to have a relatively modern libstdc++ installed.  [https://www.mail-archive.com/csgo_servers@list.valvesoftware.com/msg14291.html See this mailing list entry for further details.]&lt;br /&gt;
* [[Introduction to SourceMod Plugins#Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported?|See the current state of Counter-Strike 2 here.]]&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead&lt;br /&gt;
| &amp;lt;code&amp;gt;222840&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* This is the one first-party game that requires a [https://www.metamodsource.net/?go=vdf custom VDF file for Metamod:Source].&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2&lt;br /&gt;
| &amp;lt;code&amp;gt;222860&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Half-Life 2: Deathmatch&lt;br /&gt;
| &amp;lt;code&amp;gt;232370&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;hl2mp&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| No More Room in Hell&lt;br /&gt;
| &amp;lt;code&amp;gt;317670&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;nmrih&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Zombie Panic! Source&lt;br /&gt;
| &amp;lt;code&amp;gt;17505&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;zps&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pirates, Vikings &amp;amp; Knights II&lt;br /&gt;
| &amp;lt;code&amp;gt;17575&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;pvkii&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For post-install server configuration, take a look at the [[../Game Server Configuration|Game Server Configuration]] page.&lt;br /&gt;
&lt;br /&gt;
= Installing Metamod:Source =&lt;br /&gt;
&lt;br /&gt;
Before you can install SourceMod on your server, you must first download and install Metamod:Source. Metamod:Source (MM:S) acts as a middleware for different Source Engine games, providing a unified interface for plugins to operate on the game.&lt;br /&gt;
&lt;br /&gt;
SourceMod itself is an MM:S plugin.&lt;br /&gt;
&lt;br /&gt;
# Download [http://www.metamodsource.net/ Metamod:Source]. In most cases, you want a stable release. Use the download package according to your server's operating system.&lt;br /&gt;
#* If the latest download is unavailable, go down the &amp;amp;quot;Latest 20 Builds&amp;amp;quot; until you get to one that is.&lt;br /&gt;
#* Again, make sure you're downloading the correct package for your server; if you're using a hosted instance, it may not be using the same operating system as your personal desktop.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
#* You may need to extract the archive on, or upload the contents to a remote server.&lt;br /&gt;
#** If you are on Windows, the recommended software to use for extracting Linux (&amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt;) archives is [https://www.7-zip.org/download.html 7-zip]; to upload files remotely via FTP, use [https://winscp.net/eng/index.php WinSCP].&lt;br /&gt;
#** If you are using a GSP, refer to their control panel.  Most provide FTP access, and some also allow for uploads directly via browser.&lt;br /&gt;
# You may want to verify that the installation was successful by starting your server and running &amp;lt;tt&amp;gt;meta version&amp;lt;/tt&amp;gt;.  It should be treated as a known command at this stage.&lt;br /&gt;
#* Most games should work without further configuration, but if you find that MM:S isn't loading, you will want to [https://www.metamodsource.net/?go=vdf generate a custom VDF file].  Known games that require custom VDF files are:&lt;br /&gt;
#** Left 4 Dead 1&lt;br /&gt;
#** Third-party mods using the Source SDK base&lt;br /&gt;
#* Metamod:Source is known to fail to load on CS:GO servers running under Linux by default.  You will want to delete &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to the installation directory, plus read the information in the next bullet point.&lt;br /&gt;
#* If you are using a Linux server you have full control over, read over the [[User:Nosoop/Guide/Game Server Configuration#Platform-specific|Platform-specific setup]] information.&lt;br /&gt;
#* Additional diagnostic information about load failures is available under &amp;lt;tt&amp;gt;metamod-fatal.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Note|On server startup, you may see an error message &amp;lt;tt&amp;gt;Unable to load plugin &amp;quot;addons/metamod/bin/${platform}64/server&amp;quot;&amp;lt;/tt&amp;gt;.  This is normal behavior; the game server will always attempt to load both 32-bit and 64-bit binaries and fail on the one that doesn't match.  If you're sure that you're not running a 64-bit game server instance, you can delete &amp;lt;tt&amp;gt;addons/metamod_x64.vdf&amp;lt;/tt&amp;gt; to only load the 32-bit version, or the other way around.}}&lt;br /&gt;
&lt;br /&gt;
= Installing SourceMod =&lt;br /&gt;
&lt;br /&gt;
The following is mostly lifted from the [[Installing SourceMod]] page.&lt;br /&gt;
&lt;br /&gt;
# Download [https://www.sourcemod.net/ SourceMod]. Same as before; latest available stable release for your server's operating system.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If you plan on creating new plugins, you will also want to download SourceMod for your ''desktop'' operating system and extract the &amp;lt;code&amp;gt;addons/sourcemod/scripting/&amp;lt;/code&amp;gt; folder to a location on your computer.&lt;br /&gt;
&lt;br /&gt;
In the future, you may need to follow [[Upgrading SourceMod|these instructions to upgrade SourceMod]] on your server because of:&lt;br /&gt;
* game updates requiring SourceMod to be rebuilt against a new revision of the Source SDK&lt;br /&gt;
* plugins compiled against newer versions of SourceMod to take advantage of added functionality&lt;br /&gt;
&lt;br /&gt;
= Picking an IDE =&lt;br /&gt;
&lt;br /&gt;
Now that you have the dedicated game server, Metamod:Source, and SourceMod installed, you have most of the tools you need.&lt;br /&gt;
&lt;br /&gt;
If you've never done any programming, you'll need a text editor. It's completely possible to write code in plain old Notepad and invoke the compiler directly, but having a proper development environment makes it much easier to work with code.&lt;br /&gt;
&lt;br /&gt;
The following editors are known to have good support for SourceMod plugins:&lt;br /&gt;
&lt;br /&gt;
* Spider (highly recommended when starting out due to it being zero-install; once you have multiple projects, move on to one of the non-web text editors)&lt;br /&gt;
* BasicPawn&lt;br /&gt;
* Notepad++&lt;br /&gt;
* SPEdit&lt;br /&gt;
* Sublime Text 3&lt;br /&gt;
* Visual Studio Code (VSCode)&lt;br /&gt;
&lt;br /&gt;
For more details on each editor and, if necessary, how to set it up for writing SourceMod plugins, look at the [[../Development Environments|Development Environments]] section of the guide.&lt;br /&gt;
&lt;br /&gt;
Once you've settled on a development environment, you can start learning how to create plugins &amp;amp;mdash; head over to the [[../Basics|Basics]] section of the guide to get started.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Building_SourceMod&amp;diff=11421</id>
		<title>Building SourceMod</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Building_SourceMod&amp;diff=11421"/>
		<updated>2023-03-26T02:05:59Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Configuring */ Add note on running Python 3&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Compiling SourceMod is not difficult, but requires a number of prerequisites.  This article details the requirements and steps to being able to build working SourceMod binaries.&lt;br /&gt;
&lt;br /&gt;
Note that specific compiler versions are required to maintain ABI compatibility with Source engine binaries.&lt;br /&gt;
&lt;br /&gt;
=Requirements=&lt;br /&gt;
&lt;br /&gt;
==Windows==&lt;br /&gt;
&lt;br /&gt;
# Install Visual Studio or Visual C++. VS/VC 2010 or above is required for SourceMod 1.6.x and earlier. VS/VC 2013 Update 2 or above is required for SourceMod 1.7.x and later (Express editions should work fine). VS/VC 2015 is required for SourceMod 1.10.x or later.&lt;br /&gt;
#* If you use 2013 or higher, make sure to get the &amp;quot;Desktop&amp;quot; version: [http://www.visualstudio.com/downloads/download-visual-studio-vs#d-express-windows-desktop Visual Studio Express 2013 for Desktop].&lt;br /&gt;
#* With VS/VC 2017, you may use [https://download.visualstudio.microsoft.com/download/pr/b8d403d9-01a4-45a0-9229-db5572fd5e4e/997600ae09705dfc6d069d8ad2cfad1962d8ff6fedd6c9fe5abee36c7c919f34/vs_BuildTools.exe the build tools installer] to install the minimal set of packages.&lt;br /&gt;
#** You will want to install the following:  .NET 4.6.1 SDK and corrresponding targeting pack, C++/CLI support, VC++2015.3 v14.00 toolset for desktop, Visual C++ Build Tools core features, Windows 8.1 SDK, and Windows Universal C Runtime.&lt;br /&gt;
#** When attempting to configure and build, use the &amp;quot;VS2015 x86 Native Tools Command Prompt&amp;quot; Start Menu option to have the build tools available in the current Command Prompt's PATH.&lt;br /&gt;
#* With [https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019 Build Tools for Visual Studio 2019], you can install the following individual components:  MSVC v140 - VS 2015 C++ build tools (v14.00), Windows Universal CRT SDK, and Windows 10 SDK.&lt;br /&gt;
# Install [http://git-scm.com/ Git]. Make sure that you select the option that adds Git to PATH.&lt;br /&gt;
# Next, you will need to start an environment capable of running Python and interacting with the Visual Studio compiler.&lt;br /&gt;
#* Install [http://python.org/ Python].  Versions newer than 3.3 are supported; at the time of writing the latest available version is 3.11.&lt;br /&gt;
#* Add Python to your &amp;lt;tt&amp;gt;PATH&amp;lt;/tt&amp;gt; variable. Go to Control Panel, System, Advanced, Environment Variables. Add &amp;lt;tt&amp;gt;C:\Python27;C:\Python27\Scripts&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;PATH&amp;lt;/tt&amp;gt; (or wherever your Python install is).&lt;br /&gt;
#* Under Start, Programs, Microsoft Visual Studio, select the &amp;quot;Visual Studio Tools&amp;quot; folder and run &amp;quot;Visual Studio Command Prompt&amp;quot;. Alternately, open a normal command prompt and run &amp;lt;tt&amp;gt;&amp;quot;C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\vcvars.bat&amp;quot;&amp;lt;/tt&amp;gt;. Substitute your Visual Studio version if needed.&lt;br /&gt;
&lt;br /&gt;
==Linux==&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Install Git, via either system packages or from the [http://git-scm.com/ Git] distribution.&amp;lt;/li&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Install a C++ compiler and dependencies. SourceMod officially supports clang. For example, on Ubuntu/Debian:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install clang lib32stdc++-7-dev lib32z1-dev libc6-dev-i386 linux-libc-dev:i386&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;If building on a 64-bit system, you must install the 32-bit libraries for the compiler; e.g.:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install g++-multilib&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Archlinux==&lt;br /&gt;
&lt;br /&gt;
# Enable multilib repository as described in the [https://wiki.archlinux.org/index.php/multilib Archlinux wiki page].&lt;br /&gt;
# Install the following packages:&lt;br /&gt;
#:&amp;lt;pre&amp;gt;pacman -S git python2 gcc-multilib lib32-glibc lib32-libstdc++5 lib32-zlib&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Mac OS X==&lt;br /&gt;
Mac OS X 10.7 to 10.14 is required to build, however, SourceMod will work on 10.5. SourceMod will neither build nor run on older PPC Macs.&lt;br /&gt;
Newer versions are unsupported due to the removal of 32 bit support from MacOS.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
 &amp;lt;li&amp;gt;Install the Xcode Command Line Tools.&lt;br /&gt;
  &amp;lt;ul&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;For OS X 10.9 or higher, run the command below in Terminal and click the Install button in the window that appears.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
xcode-select --install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
    &amp;lt;/li&amp;gt;&lt;br /&gt;
    &amp;lt;li&amp;gt;For earlier versions of OS X, download and install Xcode from the App Store. Launch Xcode and then navigate to Preferences -&amp;gt; Downloads -&amp;gt; Components -&amp;gt; Command Line Tools -&amp;gt; Install. If you have recently upgraded Xcode, you will need to perform this step again. SourceMod cannot build without Xcode's command line tools.&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Downloading Source and Dependencies=&lt;br /&gt;
&lt;br /&gt;
First, grab the SourceMod source tree. We recommend placing it inside its own folder, since we'll also need to download its dependencies.&lt;br /&gt;
&lt;br /&gt;
'''You should do a recursive checkout of the git repo since the sourcepawn repo is a submodule of sourcemod now, see https://stackoverflow.com/questions/3796927/how-to-git-clone-including-submodules to do that.'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir -p alliedmodders&lt;br /&gt;
cd alliedmodders&lt;br /&gt;
git clone --recursive https://github.com/alliedmodders/sourcemod&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, run the &amp;lt;tt&amp;gt;checkout-deps.sh&amp;lt;/tt&amp;gt; script. This will download all dependencies and attempt to install AMBuild. If you are using Linux or OS X, it may prompt you for your sudo password at the very end. If you want to skip this and install AMBuild manually, just Ctrl+C. (Do not run the checkout script with sudo.)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bash sourcemod/tools/checkout-deps.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After it's done, you should see a large number of hl2sdk folders and other assorted dependencies, like MySQL, Metamod:Source, and AMBuild.&lt;br /&gt;
&lt;br /&gt;
If you are on Windows, you can use 'checkout-deps' PowerShell script (if it exists), you just may need to swap ExecutionPolicy to a less restrictive one. (See: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies).&lt;br /&gt;
&lt;br /&gt;
Otherwise, you can manually download the dependencies with the commands below:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone --mirror https://github.com/alliedmodders/hl2sdk hl2sdk-proxy-repo&lt;br /&gt;
# For each SDK you want to build with:&lt;br /&gt;
# git clone hl2sdk-proxy-repo hl2sdk-&amp;lt;SDK&amp;gt; -b &amp;lt;SDK&amp;gt;&lt;br /&gt;
# e.g. git clone hl2sdk-proxy-repo hl2sdk-csgo -b csgo&lt;br /&gt;
&lt;br /&gt;
git clone https://github.com/alliedmodders/metamod-source mmsource-1.10 -b 1.10-dev&lt;br /&gt;
&lt;br /&gt;
# If building version 1.10 of SourceMod, use MySQL 5.5&lt;br /&gt;
wget https://cdn.mysql.com/archives/mysql-5.5/mysql-5.5.54-win32.zip mysql-5.5&lt;br /&gt;
&lt;br /&gt;
# If building &amp;lt; version 1.10 of SourceMod, use MySQL 5.0&lt;br /&gt;
wget https://cdn.mysql.com/archives/mysql-5.0/mysql-noinstall-5.0.24a-win32.zip mysql-5.0&lt;br /&gt;
&lt;br /&gt;
# Install AMBuild&lt;br /&gt;
git clone https://github.com/alliedmodders/ambuild&lt;br /&gt;
pip install ./ambuild&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that you can skip MySQL and SDK versions you don't plan to build.&lt;br /&gt;
&lt;br /&gt;
=Configuring=&lt;br /&gt;
&lt;br /&gt;
The first time you are building a SourceMod tree, you must ''configure'' the build. This step initializes some basic information and allows some customization around how things get compiled.&lt;br /&gt;
&lt;br /&gt;
First create a build folder within your sourcemod folder, and then run &amp;lt;tt&amp;gt;configure.py&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd sourcemod&lt;br /&gt;
mkdir build&lt;br /&gt;
cd build&lt;br /&gt;
python ../configure.py&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note:''' If it complains about &amp;lt;tt&amp;gt;Could not find a source copy of Metamod:Source&amp;lt;/tt&amp;gt;, rename the &amp;lt;tt&amp;gt;mmsource-11&amp;lt;/tt&amp;gt; folder to &amp;lt;tt&amp;gt;metamod-source&amp;lt;/tt&amp;gt;. See https://github.com/alliedmodders/sourcemod/blob/master/AMBuildScript#L186-L193 for the valid folder names it looks for&lt;br /&gt;
&lt;br /&gt;
You may also need to run Python as &amp;lt;tt&amp;gt;python3&amp;lt;/tt&amp;gt; instead of &amp;lt;tt&amp;gt;python&amp;lt;/tt&amp;gt;, depending on your operating system's installed Python version(s).&lt;br /&gt;
&lt;br /&gt;
It is safe to reconfigure over an old build. However, it's probably a bad idea to configure inside a random, non-empty folder.&lt;br /&gt;
&lt;br /&gt;
There are a few extra options you can pass to &amp;lt;tt&amp;gt;configure&amp;lt;/tt&amp;gt;:&lt;br /&gt;
*--enable-debug - Compile with symbols and debug checks/assertions.&lt;br /&gt;
*--enable-optimize - Compile with optimizations.&lt;br /&gt;
*--no-sse - Disable floating point optimizations (if you have a very, very old CPU).&lt;br /&gt;
*--no-mysql - Don't build the MySQL database module.&lt;br /&gt;
*--sdks css - Only build css.&lt;br /&gt;
&lt;br /&gt;
See configure.py for all the options.&lt;br /&gt;
&lt;br /&gt;
=Building=&lt;br /&gt;
&lt;br /&gt;
To build SourceMod, simply type:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ambuild&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your build folder. Alternately, you can specify the path of the build folder:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ambuild debug-build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The full package layout that would be shipped for release is in the &amp;lt;tt&amp;gt;package&amp;lt;/tt&amp;gt; folder of the build.&lt;br /&gt;
&lt;br /&gt;
=Deprecated Tools=&lt;br /&gt;
==Visual Studio Project Files==&lt;br /&gt;
In the future, we will use AMBuild to automatically generate project files, and the existing project files will be removed from the SourceMod tree. In the meantime however, it is possible to use these files. Unfortunately, they require a bit of extra work to use.&lt;br /&gt;
&lt;br /&gt;
First, make sure you've downloaded all necessary dependencies (SDKs, Metamod:Source source code, and MySQL) via the &amp;lt;tt&amp;gt;checkout-windows-deps.bat&amp;lt;/tt&amp;gt; script. Next,&lt;br /&gt;
#Open the Control Panel (for example, via Start -&amp;gt; Settings).&lt;br /&gt;
#Open the System control.  If you don't see it, you may need to switch to &amp;quot;Classic view&amp;quot; (either via the left-hand pane or by going to Tools -&amp;gt; Folder Options).&lt;br /&gt;
#Click the Advanced tab.&lt;br /&gt;
#Click the Environment Variables button.&lt;br /&gt;
&lt;br /&gt;
Now, add your environment variables to either your User settings or your System settings. Create a new variable for each item in the list below. You may omit SDKs that you do not plan to build against. The item names are in &amp;lt;tt&amp;gt;fixed-width font&amp;lt;/tt&amp;gt; and their value descriptions follow.&lt;br /&gt;
*&amp;lt;tt&amp;gt;MMSOURCE19&amp;lt;/tt&amp;gt; - Path to Metamod:Source 1.10+&lt;br /&gt;
*&amp;lt;tt&amp;gt;MMSOURCE18&amp;lt;/tt&amp;gt; - Path to Metamod:Source 1.10+&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDK&amp;lt;/tt&amp;gt; - Path to HL2SDK Ep1/Original&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDKOB&amp;lt;/tt&amp;gt; - Path to HL2SDK Ep2/OrangeBox for mods&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDKOBVALVE&amp;lt;/tt&amp;gt; - Path to HL2SDK Source 2009 (HL2:DM, DoD:S, TF2)&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDK-SWARM&amp;lt;/tt&amp;gt; - Path to HL2SDK Alien Swarm&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDK-BGT&amp;lt;/tt&amp;gt; - Path to HL2SDK for Bloody Good Time&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDKCSGO&amp;lt;/tt&amp;gt; - Path to HL2SDK CS:GO&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDKCSS&amp;lt;/tt&amp;gt; - Path to HL2SDK CS:S&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDK-DARKM&amp;lt;/tt&amp;gt; - Path to HL2SDK Dark Messiah&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDK-EYE&amp;lt;/tt&amp;gt; - Path to HL2SDK E.Y.E.: Divine Cybermancy&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDKL4D&amp;lt;/tt&amp;gt; - Path to HL2SDK L4D1&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDKL4D2&amp;lt;/tt&amp;gt; - Path to HL2SDK L4D2&lt;br /&gt;
*&amp;lt;tt&amp;gt;HL2SDK-DOTA&amp;lt;/tt&amp;gt; - Path to HL2SDK DOTA 2&lt;br /&gt;
*&amp;lt;tt&amp;gt;MYSQL5&amp;lt;/tt&amp;gt; - Path to the folder that contains MySQL's &amp;lt;tt&amp;gt;include&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;lib&amp;lt;/tt&amp;gt; folders.&lt;br /&gt;
&lt;br /&gt;
==Makefiles==&lt;br /&gt;
Makefiles are deprecated and will be removed from the tree soon.&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Documentation]]&lt;br /&gt;
[[Category:SourceMod Development]]&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11419</id>
		<title>User:Nosoop/Guide/Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11419"/>
		<updated>2023-03-25T16:10:16Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Installing the Server */ Link the relevant SteamCMD sections&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section assumes that you're starting out with nothing besides a desktop computer, an internet connection, and a drive to program some SourceMod plugins. No programming experience; no problem.&lt;br /&gt;
&lt;br /&gt;
This page will walk you through manually installing the dedicated server software for your desired game, installing SourceMod, and selecting a text editor to use for development.&lt;br /&gt;
&lt;br /&gt;
There are a number of third-party tools that can automate most of these steps, but we'll stick to the first-party approach here to avoid abstractions from breaking under you.&lt;br /&gt;
&lt;br /&gt;
If you are using a third-party tool to manage your server installation, refer to the tool's documentation for their instructions, then skip to [[#Installing SourceMod|Installing SourceMod]] to download the scripting toolchain for your desktop operating system.&lt;br /&gt;
&lt;br /&gt;
= Installing the Server =&lt;br /&gt;
&lt;br /&gt;
{{note|&amp;lt;p&amp;gt;While officially unsupported, SourceMod may be loaded on a game client (the game you launch); the server a game client creates is known as a listen server. However, there are many behavioral quirks that can only be reproduced on a listen server, and you likely won't receive any solutions to those issues that aren't &amp;quot;use a dedicated server&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This guide does not provide instructions to load SourceMod on a game client. It's highly recommended to stick to installing SourceMod on dedicated game server instances to ensure that any plugins you write will have the correct behavior.&amp;lt;/p&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
To install the dedicated server software for the game of your choice, we will use &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt;. If a game server provider (GSP) is hosting the server for you, skip this step as your provider has already provided you with an installation; if you are using a self-hosted game server management panel, refer to the instructions for your software of choice to install your game server in place of this step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is Valve's command-line Steam client. It is used to install and update dedicated game servers.&lt;br /&gt;
&lt;br /&gt;
Refer to [https://developer.valvesoftware.com/wiki/SteamCMD the SteamCMD entry] in the Valve Developer Wiki for download instructions. This varies on the operating system you're running the software on; you can either work on your own desktop or have a hosted (physical or virtual) machine off-premises.&lt;br /&gt;
&lt;br /&gt;
Once &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is extracted, you will need to install a game. Continue reading the above wiki page to [https://developer.valvesoftware.com/wiki/SteamCMD#Running_SteamCMD run the application], [https://developer.valvesoftware.com/wiki/SteamCMD#SteamCMD_Login sign in (anonymously)], and [https://developer.valvesoftware.com/wiki/SteamCMD#Downloading_an_App download your game server].&lt;br /&gt;
&lt;br /&gt;
You will need the AppID of the game's dedicated server to install it; note that it is different from the game client AppIDs.  See the below table for that and additional related information for some of the supported games.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Dedicated Server Information&lt;br /&gt;
|-&lt;br /&gt;
! Game&lt;br /&gt;
! AppID&lt;br /&gt;
! Mod Directory&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Day of Defeat: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232290&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;dod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Team Fortress 2&lt;br /&gt;
| &amp;lt;code&amp;gt;232250&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;tf&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232330&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;cstrike&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Global Offensive&lt;br /&gt;
| &amp;lt;code&amp;gt;740&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* As of 1.38.5.2 (2023-02-02), servers running under Linux will need to have a relatively modern libstdc++ installed.  [https://www.mail-archive.com/csgo_servers@list.valvesoftware.com/msg14291.html See this mailing list entry for further details.]&lt;br /&gt;
* [[Introduction to SourceMod Plugins#Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported?|See the current state of Counter-Strike 2 here.]]&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead&lt;br /&gt;
| &amp;lt;code&amp;gt;222840&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* This is the one first-party game that requires a [https://www.metamodsource.net/?go=vdf custom VDF file for Metamod:Source].&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2&lt;br /&gt;
| &amp;lt;code&amp;gt;222860&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Half-Life 2: Deathmatch&lt;br /&gt;
| &amp;lt;code&amp;gt;232370&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;hl2mp&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| No More Room in Hell&lt;br /&gt;
| &amp;lt;code&amp;gt;317670&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;nmrih&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Zombie Panic! Source&lt;br /&gt;
| &amp;lt;code&amp;gt;17505&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;zps&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pirates, Vikings &amp;amp; Knights II&lt;br /&gt;
| &amp;lt;code&amp;gt;17575&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;pvkii&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For post-install server configuration, take a look at the [[../Game Server Configuration|Game Server Configuration]] page.&lt;br /&gt;
&lt;br /&gt;
= Installing Metamod:Source =&lt;br /&gt;
&lt;br /&gt;
Before you can install SourceMod on your server, you must first download and install Metamod:Source. Metamod:Source (MM:S) acts as a middleware for different Source Engine games, providing a unified interface for plugins to operate on the game.&lt;br /&gt;
&lt;br /&gt;
SourceMod itself is an MM:S plugin.&lt;br /&gt;
&lt;br /&gt;
# Download [http://www.metamodsource.net/ Metamod:Source]. In most cases, you want a stable release. Use the download package according to your server's operating system.&lt;br /&gt;
#* If the latest download is unavailable, go down the &amp;amp;quot;Latest 20 Builds&amp;amp;quot; until you get to one that is.&lt;br /&gt;
#* Again, make sure you're downloading the correct package for your server; if you're using a hosted instance, it may not be using the same operating system as your personal desktop.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
#*You may need to extract the archive on, or upload the contents to a remote server.&lt;br /&gt;
#**If you are on Windows, the recommended software to use for extracting Linux (&amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt;) archives is [https://www.7-zip.org/download.html 7-zip]; to upload files remotely via FTP, use [https://winscp.net/eng/index.php WinSCP].&lt;br /&gt;
#**If you are using a GSP, refer to their control panel.  Most provide FTP access, and some also allow for uploads directly via browser.&lt;br /&gt;
# You may want to verify that the installation was successful by starting your server and running &amp;lt;tt&amp;gt;meta version&amp;lt;/tt&amp;gt;.  It should be treated as a known command at this stage.&lt;br /&gt;
#* Most games should work without further configuration, but if you find that MM:S isn't loading, you will want to [https://www.metamodsource.net/?go=vdf generate a custom VDF file].  Known games that require custom VDF files are:&lt;br /&gt;
#** Left 4 Dead 1&lt;br /&gt;
#** Third-party mods using the Source SDK base&lt;br /&gt;
#* Metamod:Source is known to fail to load on CS:GO servers running under Linux by default.  You will want to delete &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to the installation directory, plus read the information in the next bullet point.&lt;br /&gt;
#* If you are using a Linux server you have full control over, read over the [[User:Nosoop/Guide/Game Server Configuration#Platform-specific|Platform-specific setup]] information.&lt;br /&gt;
#* Additional diagnostic information about load failures is available under &amp;lt;tt&amp;gt;metamod-fatal.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Note|On server startup, you may see an error message &amp;lt;tt&amp;gt;Unable to load plugin &amp;quot;addons/metamod/bin/${platform}64/server&amp;quot;&amp;lt;/tt&amp;gt;.  This is normal behavior; the game server will always attempt to load both 32-bit and 64-bit binaries and fail on the one that doesn't match.  If you're sure that you're not running a 64-bit game server instance, you can delete &amp;lt;tt&amp;gt;addons/metamod_x64.vdf&amp;lt;/tt&amp;gt; to only load the 32-bit version, or the other way around.}}&lt;br /&gt;
&lt;br /&gt;
= Installing SourceMod =&lt;br /&gt;
&lt;br /&gt;
The following is mostly lifted from the [[Installing SourceMod]] page.&lt;br /&gt;
&lt;br /&gt;
# Download [https://www.sourcemod.net/ SourceMod]. Same as before; latest available stable release for your server's operating system.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If you plan on creating new plugins, you will also want to download SourceMod for your ''desktop'' operating system and extract the &amp;lt;code&amp;gt;addons/sourcemod/scripting/&amp;lt;/code&amp;gt; folder to a location on your computer.&lt;br /&gt;
&lt;br /&gt;
In the future, you may need to follow [[Upgrading SourceMod|these instructions to upgrade SourceMod]] on your server because of:&lt;br /&gt;
* game updates requiring SourceMod to be rebuilt against a new revision of the Source SDK&lt;br /&gt;
* plugins compiled against newer versions of SourceMod to take advantage of added functionality&lt;br /&gt;
&lt;br /&gt;
= Picking an IDE =&lt;br /&gt;
&lt;br /&gt;
Now that you have the dedicated game server, Metamod:Source, and SourceMod installed, you have most of the tools you need.&lt;br /&gt;
&lt;br /&gt;
If you've never done any programming, you'll need a text editor. It's completely possible to write code in plain old Notepad and invoke the compiler directly, but having a proper development environment makes it much easier to work with code.&lt;br /&gt;
&lt;br /&gt;
The following editors are known to have good support for SourceMod plugins:&lt;br /&gt;
&lt;br /&gt;
* Spider (highly recommended when starting out due to it being zero-install; once you have multiple projects, move on to one of the non-web text editors)&lt;br /&gt;
* BasicPawn&lt;br /&gt;
* Notepad++&lt;br /&gt;
* SPEdit&lt;br /&gt;
* Sublime Text 3&lt;br /&gt;
* Visual Studio Code (VSCode)&lt;br /&gt;
&lt;br /&gt;
For more details on each editor and, if necessary, how to set it up for writing SourceMod plugins, look at the [[../Development Environments|Development Environments]] section of the guide.&lt;br /&gt;
&lt;br /&gt;
Once you've settled on a development environment, you can start learning how to create plugins &amp;amp;mdash; head over to the [[../Basics|Basics]] section of the guide to get started.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11418</id>
		<title>User:Nosoop/Guide/Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/Setup&amp;diff=11418"/>
		<updated>2023-03-25T11:10:15Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Installing the Server */ Convert the dedicated server list to a table&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section assumes that you're starting out with nothing besides a desktop computer, an internet connection, and a drive to program some SourceMod plugins. No programming experience; no problem.&lt;br /&gt;
&lt;br /&gt;
This page will walk you through manually installing the dedicated server software for your desired game, installing SourceMod, and selecting a text editor to use for development.&lt;br /&gt;
&lt;br /&gt;
There are a number of third-party tools that can automate most of these steps, but we'll stick to the first-party approach here to avoid abstractions from breaking under you.&lt;br /&gt;
&lt;br /&gt;
If you are using a third-party tool to manage your server installation, refer to the tool's documentation for their instructions, then skip to [[#Installing SourceMod|Installing SourceMod]] to download the scripting toolchain for your desktop operating system.&lt;br /&gt;
&lt;br /&gt;
= Installing the Server =&lt;br /&gt;
&lt;br /&gt;
{{note|&amp;lt;p&amp;gt;While officially unsupported, SourceMod may be loaded on a game client (the game you launch); the server a game client creates is known as a listen server. However, there are many behavioral quirks that can only be reproduced on a listen server, and you likely won't receive any solutions to those issues that aren't &amp;quot;use a dedicated server&amp;quot;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;This guide does not provide instructions to load SourceMod on a game client. It's highly recommended to stick to installing SourceMod on dedicated game server instances to ensure that any plugins you write will have the correct behavior.&amp;lt;/p&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
To install the dedicated server software for the game of your choice, we will use &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt;. If a game server provider (GSP) is hosting the server for you, skip this step as your provider has already provided you with an installation; if you are using a self-hosted game server management panel, refer to the instructions for your software of choice to install your game server in place of this step.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is Valve's command-line Steam client. It is used to install and update dedicated game servers.&lt;br /&gt;
&lt;br /&gt;
Refer to the [https://developer.valvesoftware.com/wiki/SteamCMD SteamCMD] section in the Valve Developer Wiki for download instructions. This varies on the operating system you're running the software on; you can either work on your own desktop or have a hosted (physical or virtual) machine off-premises.&lt;br /&gt;
&lt;br /&gt;
Once &amp;lt;code&amp;gt;steamcmd&amp;lt;/code&amp;gt; is extracted, you will need to install a game. Continue reading the above wiki page to run the application, sign in (anonymously), and download your game server.&lt;br /&gt;
&lt;br /&gt;
You will need the AppID of the game's dedicated server to install it; note that it is different from the game client AppIDs.  See the below table for that and additional related information for some of the supported games.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Dedicated Server Information&lt;br /&gt;
|-&lt;br /&gt;
! Game&lt;br /&gt;
! AppID&lt;br /&gt;
! Mod Directory&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Day of Defeat: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232290&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;dod&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Team Fortress 2&lt;br /&gt;
| &amp;lt;code&amp;gt;232250&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;tf&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Source&lt;br /&gt;
| &amp;lt;code&amp;gt;232330&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;cstrike&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Counter-Strike: Global Offensive&lt;br /&gt;
| &amp;lt;code&amp;gt;740&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;csgo&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* As of 1.38.5.2 (2023-02-02), servers running under Linux will need to have a relatively modern libstdc++ installed.  [https://www.mail-archive.com/csgo_servers@list.valvesoftware.com/msg14291.html See this mailing list entry for further details.]&lt;br /&gt;
* [[Introduction to SourceMod Plugins#Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported?|See the current state of Counter-Strike 2 here.]]&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead&lt;br /&gt;
| &amp;lt;code&amp;gt;222840&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead&amp;lt;/code&amp;gt;&lt;br /&gt;
|&lt;br /&gt;
* This is the one first-party game that requires a [https://www.metamodsource.net/?go=vdf custom VDF file for Metamod:Source].&lt;br /&gt;
|-&lt;br /&gt;
| Left 4 Dead 2&lt;br /&gt;
| &amp;lt;code&amp;gt;222860&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;left4dead2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Half-Life 2: Deathmatch&lt;br /&gt;
| &amp;lt;code&amp;gt;232370&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;hl2mp&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| No More Room in Hell&lt;br /&gt;
| &amp;lt;code&amp;gt;317670&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;nmrih&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Zombie Panic! Source&lt;br /&gt;
| &amp;lt;code&amp;gt;17505&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;zps&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pirates, Vikings &amp;amp; Knights II&lt;br /&gt;
| &amp;lt;code&amp;gt;17575&amp;lt;/code&amp;gt;&lt;br /&gt;
| &amp;lt;code&amp;gt;pvkii&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For post-install server configuration, take a look at the [[../Game Server Configuration|Game Server Configuration]] page.&lt;br /&gt;
&lt;br /&gt;
= Installing Metamod:Source =&lt;br /&gt;
&lt;br /&gt;
Before you can install SourceMod on your server, you must first download and install Metamod:Source. Metamod:Source (MM:S) acts as a middleware for different Source Engine games, providing a unified interface for plugins to operate on the game.&lt;br /&gt;
&lt;br /&gt;
SourceMod itself is an MM:S plugin.&lt;br /&gt;
&lt;br /&gt;
# Download [http://www.metamodsource.net/ Metamod:Source]. In most cases, you want a stable release. Use the download package according to your server's operating system.&lt;br /&gt;
#* If the latest download is unavailable, go down the &amp;amp;quot;Latest 20 Builds&amp;amp;quot; until you get to one that is.&lt;br /&gt;
#* Again, make sure you're downloading the correct package for your server; if you're using a hosted instance, it may not be using the same operating system as your personal desktop.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
#*You may need to extract the archive on, or upload the contents to a remote server.&lt;br /&gt;
#**If you are on Windows, the recommended software to use for extracting Linux (&amp;lt;tt&amp;gt;.tar.gz&amp;lt;/tt&amp;gt;) archives is [https://www.7-zip.org/download.html 7-zip]; to upload files remotely via FTP, use [https://winscp.net/eng/index.php WinSCP].&lt;br /&gt;
#**If you are using a GSP, refer to their control panel.  Most provide FTP access, and some also allow for uploads directly via browser.&lt;br /&gt;
# You may want to verify that the installation was successful by starting your server and running &amp;lt;tt&amp;gt;meta version&amp;lt;/tt&amp;gt;.  It should be treated as a known command at this stage.&lt;br /&gt;
#* Most games should work without further configuration, but if you find that MM:S isn't loading, you will want to [https://www.metamodsource.net/?go=vdf generate a custom VDF file].  Known games that require custom VDF files are:&lt;br /&gt;
#** Left 4 Dead 1&lt;br /&gt;
#** Third-party mods using the Source SDK base&lt;br /&gt;
#* Metamod:Source is known to fail to load on CS:GO servers running under Linux by default.  You will want to delete &amp;lt;tt&amp;gt;bin/libgcc_s.so.1&amp;lt;/tt&amp;gt; relative to the installation directory, plus read the information in the next bullet point.&lt;br /&gt;
#* If you are using a Linux server you have full control over, read over the [[User:Nosoop/Guide/Game Server Configuration#Platform-specific|Platform-specific setup]] information.&lt;br /&gt;
#* Additional diagnostic information about load failures is available under &amp;lt;tt&amp;gt;metamod-fatal.log&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Note|On server startup, you may see an error message &amp;lt;tt&amp;gt;Unable to load plugin &amp;quot;addons/metamod/bin/${platform}64/server&amp;quot;&amp;lt;/tt&amp;gt;.  This is normal behavior; the game server will always attempt to load both 32-bit and 64-bit binaries and fail on the one that doesn't match.  If you're sure that you're not running a 64-bit game server instance, you can delete &amp;lt;tt&amp;gt;addons/metamod_x64.vdf&amp;lt;/tt&amp;gt; to only load the 32-bit version, or the other way around.}}&lt;br /&gt;
&lt;br /&gt;
= Installing SourceMod =&lt;br /&gt;
&lt;br /&gt;
The following is mostly lifted from the [[Installing SourceMod]] page.&lt;br /&gt;
&lt;br /&gt;
# Download [https://www.sourcemod.net/ SourceMod]. Same as before; latest available stable release for your server's operating system.&lt;br /&gt;
# Copy the contents of the archive into your game's mod directory (one level below &amp;lt;code&amp;gt;srcds.exe&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;srcds_run&amp;lt;/code&amp;gt;; the mod directory should contain &amp;lt;code&amp;gt;steam.inf&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
If you plan on creating new plugins, you will also want to download SourceMod for your ''desktop'' operating system and extract the &amp;lt;code&amp;gt;addons/sourcemod/scripting/&amp;lt;/code&amp;gt; folder to a location on your computer.&lt;br /&gt;
&lt;br /&gt;
In the future, you may need to follow [[Upgrading SourceMod|these instructions to upgrade SourceMod]] on your server because of:&lt;br /&gt;
* game updates requiring SourceMod to be rebuilt against a new revision of the Source SDK&lt;br /&gt;
* plugins compiled against newer versions of SourceMod to take advantage of added functionality&lt;br /&gt;
&lt;br /&gt;
= Picking an IDE =&lt;br /&gt;
&lt;br /&gt;
Now that you have the dedicated game server, Metamod:Source, and SourceMod installed, you have most of the tools you need.&lt;br /&gt;
&lt;br /&gt;
If you've never done any programming, you'll need a text editor. It's completely possible to write code in plain old Notepad and invoke the compiler directly, but having a proper development environment makes it much easier to work with code.&lt;br /&gt;
&lt;br /&gt;
The following editors are known to have good support for SourceMod plugins:&lt;br /&gt;
&lt;br /&gt;
* Spider (highly recommended when starting out due to it being zero-install; once you have multiple projects, move on to one of the non-web text editors)&lt;br /&gt;
* BasicPawn&lt;br /&gt;
* Notepad++&lt;br /&gt;
* SPEdit&lt;br /&gt;
* Sublime Text 3&lt;br /&gt;
* Visual Studio Code (VSCode)&lt;br /&gt;
&lt;br /&gt;
For more details on each editor and, if necessary, how to set it up for writing SourceMod plugins, look at the [[../Development Environments|Development Environments]] section of the guide.&lt;br /&gt;
&lt;br /&gt;
Once you've settled on a development environment, you can start learning how to create plugins &amp;amp;mdash; head over to the [[../Basics|Basics]] section of the guide to get started.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Scripting_FAQ_(SourceMod)&amp;diff=11417</id>
		<title>Scripting FAQ (SourceMod)</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Scripting_FAQ_(SourceMod)&amp;diff=11417"/>
		<updated>2023-03-23T15:45:07Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* How do I learn SourcePawn? */ Remove underscores from cross-page link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Yak.gif]]&lt;br /&gt;
yak wuz heer&lt;br /&gt;
&lt;br /&gt;
=How do I learn SourcePawn?=&lt;br /&gt;
A good start is on the [[Introduction to SourcePawn 1.7]] page, which will teach you the SourcePawn language. Then go through the [[Introduction to SourceMod Plugins]], which will teach you how to write your first plug-in.&lt;br /&gt;
&lt;br /&gt;
=Where can I find all the SourcePawn functions and other information?=&lt;br /&gt;
All SourceMod plug-ins have this line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This line instructs the compiler to retrieve the file &amp;lt;tt&amp;gt;sourcemod.inc&amp;lt;/tt&amp;gt; from the &amp;lt;tt&amp;gt;sourcemod/scripting/include&amp;lt;/tt&amp;gt; folder. Every function, variable, and definition can be found in the &amp;lt;tt&amp;gt;.inc&amp;lt;/tt&amp;gt; files inside the &amp;lt;tt&amp;gt;sourcemod/scripting/include&amp;lt;/tt&amp;gt; folder.&lt;br /&gt;
&lt;br /&gt;
But searching through all those files can be quite tedious. Thankfully, the honourable [https://forums.alliedmods.net/member.php?u=9443 Nican] created an API reference viewable on the web, complete with searching and commenting: [https://sm.alliedmods.net/new-api/ https://sm.alliedmods.net/new-api/]&lt;br /&gt;
&lt;br /&gt;
Also, if you are in the AlliedMods Discord server (https://discord.gg/HUc67zN), you can use the &amp;lt;tt&amp;gt;/docs&amp;lt;/tt&amp;gt; command to search the API.&lt;br /&gt;
&lt;br /&gt;
=How do I find the classname of an entity? (e.g., &amp;quot;&amp;lt;tt&amp;gt;weapon_knife&amp;lt;/tt&amp;gt;&amp;quot; or &amp;quot;&amp;lt;tt&amp;gt;prop_physics&amp;lt;/tt&amp;gt;&amp;quot;)=&lt;br /&gt;
The classname of an entity (not to be confused with a netclass such as &amp;lt;tt&amp;gt;CCSPlayer&amp;lt;/tt&amp;gt;) is a unique identifier. It's the most well known of entity names. To find it, use the function [https://sm.alliedmods.net/new-api/entity/GetEdictClassname GetEdictClassname()]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;char classname[128];&lt;br /&gt;
GetEdictClassname(myentity, classname, sizeof(classname));&lt;br /&gt;
&lt;br /&gt;
PrintToServer(&amp;quot;myentity classname: %s&amp;quot;, classname);&lt;br /&gt;
// myentity classname: weapon_knife&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=How do I block regular commands, such as &amp;lt;tt&amp;gt;kill&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;say&amp;lt;/tt&amp;gt;?=&lt;br /&gt;
As of version 1.3, the recommended way to hook and block commands is with [https://sm.alliedmods.net/new-api/console/AddCommandListener AddCommandListener()]. Previously, using [https://sm.alliedmods.net/new-api/console/RegConsoleCmd RegConsoleCmd()] with the command name was the only way to hook commands, but this creates a whole new command for the command dispatch to check every time any command is executed. [https://sm.alliedmods.net/new-api/console/AddCommandListener AddCommandListener()] creates only a lightweight hook, processed only when the specific command is executed.&lt;br /&gt;
&lt;br /&gt;
Here's how to use it to block the &amp;lt;tt&amp;gt;say&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    AddCommandListener(SayCallback, &amp;quot;say&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action SayCallback(int client, const char[] command, int argc)&lt;br /&gt;
{&lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=How do I hook +commands, such as &amp;lt;tt&amp;gt;+zoom&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;+attack&amp;lt;/tt&amp;gt;?=&lt;br /&gt;
Unlike regular commands, &amp;lt;tt&amp;gt;+commands&amp;lt;/tt&amp;gt; are handled on the client's computer, then sent to the server in a more compressed fashion. This means [https://sm.alliedmods.net/new-api/console/AddCommandListener AddCommandListener()] cannot be used to hook &amp;lt;tt&amp;gt;+commands&amp;lt;/tt&amp;gt;. As of version 1.3, the recommended solution is to use the global forward [https://sm.alliedmods.net/new-api/sdktools_hooks/OnPlayerRunCmd OnPlayerRunCmd()]. This forward is fired every time a player uses a movement button. To detect or block a &amp;lt;tt&amp;gt;+command&amp;lt;/tt&amp;gt;, you'll first have to find out its proper &amp;lt;tt&amp;gt;IN_&amp;lt;/tt&amp;gt; constant (see &amp;lt;tt&amp;gt;[https://sm.alliedmods.net/new-api/entity_prop_stocks/__raw entity_prop_stocks.inc]&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Here's how to use it to block crouching when attacking:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Action OnPlayerRunCmd(int client, int &amp;amp;buttons, int &amp;amp;impulse, float vel[3], float angles[3], int &amp;amp;weapon)&lt;br /&gt;
{&lt;br /&gt;
    // Check if the player is attacking (+attack)&lt;br /&gt;
    if ((buttons &amp;amp; IN_ATTACK) == IN_ATTACK)&lt;br /&gt;
    {&lt;br /&gt;
        // If so, block their crouching (+duck)&lt;br /&gt;
        buttons &amp;amp;= ~IN_DUCK;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // We must return Plugin_Continue to let the changes be processed.&lt;br /&gt;
    // Otherwise, we can return Plugin_Handled to block the commands&lt;br /&gt;
    return Plugin_Continue;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=How do I get rid of loose indentation warnings?=&lt;br /&gt;
&amp;lt;pre&amp;gt;myplugin.sp(#) : warning 217: loose indentation&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Loose indentation warnings arise when indentation in your code is inconsistent. This usually means using both tabs and spaces as indentation. However, it can also mean a different amount of spaces or tabs are being used. Therefore, to correct it, use just one type of indentation. Because different editors have different settings for the size of tab stops, it is recommended you use 4 spaces to indent.&lt;br /&gt;
&lt;br /&gt;
Good:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    int myvar = 5;&lt;br /&gt;
    if (myvar == (2 + 3))&lt;br /&gt;
        PrintToServer(&amp;quot;myvar is %d&amp;quot;, myvar);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bad:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public voidOnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	int myvar = 5;&lt;br /&gt;
    if (myvar == (2 + 3))&lt;br /&gt;
		PrintToServer(&amp;quot;myvar is %d&amp;quot;, myvar);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=How do I get rid of tag mismatch warnings?=&lt;br /&gt;
Though every variable in SourcePawn is one cell (4 bytes), with the exception of strings, there are many different ways to interpret what's inside a cell. To signify a cell's contents, tags are used. The most common are &amp;lt;tt&amp;gt;_&amp;lt;/tt&amp;gt; (the default tag: a vanilla cell. This tag is implied when no other tag is specified.), &amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;bool&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt;. See [[Introduction_to_SourcePawn_1.7#Variables_2]] for more information.&lt;br /&gt;
&lt;br /&gt;
Functions wear these tags on their parameters so you can tell what needs to be passed to the function:&lt;br /&gt;
&amp;lt;pawn&amp;gt;native int SetEntPropFloat(int entity, PropType type, const char[] prop, float value, int element)&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function calls for '''&amp;lt;tt&amp;gt;entity&amp;lt;/tt&amp;gt;''', a cell with the implied tag '''''&amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;'''''; '''&amp;lt;tt&amp;gt;type&amp;lt;/tt&amp;gt;''', with the developer-defined tag '''''&amp;lt;tt&amp;gt;PropType&amp;lt;/tt&amp;gt;'''''; '''&amp;lt;tt&amp;gt;prop&amp;lt;/tt&amp;gt;''', with the built-in tag '''''&amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt;'''''; and '''&amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;''', with the built-in tag '''''&amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;'''''.&lt;br /&gt;
To call this function, then, you must pass values with the specified tags. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;SetEntPropFloat(1234, Prop_Send, &amp;quot;m_fNumber&amp;quot;, 1.0);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This calls the function correctly: &amp;lt;tt&amp;gt;1234&amp;lt;/tt&amp;gt; is a regular cell ('''''&amp;lt;tt&amp;gt;_&amp;lt;/tt&amp;gt;'''''), &amp;lt;tt&amp;gt;Prop_Send&amp;lt;/tt&amp;gt; is a variable defined in the enum '''''&amp;lt;tt&amp;gt;PropType&amp;lt;/tt&amp;gt;''''' in [https://sm.alliedmods.net/new-api/entity/__raw entity.inc], &amp;lt;tt&amp;gt;&amp;quot;m_fNumber&amp;quot;&amp;lt;/tt&amp;gt; is a '''''&amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt;''''', and &amp;lt;tt&amp;gt;1.0&amp;lt;/tt&amp;gt; is a '''''&amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;'''''. For a nonexample:&lt;br /&gt;
&amp;lt;pawn&amp;gt;SetEntPropFloat(1234.0, 1, &amp;quot;m_fNumber&amp;quot;, 1337);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is incorrect! &amp;lt;tt&amp;gt;1234.0&amp;lt;/tt&amp;gt; is a '''''&amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;''''' that should be a regular cell ('''''&amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;'''''); &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; is a regular cell ('''''&amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;''''') that should be a '''''&amp;lt;tt&amp;gt;PropType&amp;lt;/tt&amp;gt;'''''; and &amp;lt;tt&amp;gt;1337&amp;lt;/tt&amp;gt; is a regular cell ('''''&amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt;''''') that should be a '''''&amp;lt;tt&amp;gt;float&amp;lt;/tt&amp;gt;'''''. This call will generate a tag mismatch warning. To correct it, simply use a value with the correct tag. Most of the time, tags that are not built-in (such as '''''&amp;lt;tt&amp;gt;PropType&amp;lt;/tt&amp;gt;''''') can be found in the same file where a function uses them (you can find '''''&amp;lt;tt&amp;gt;PropType&amp;lt;/tt&amp;gt;''''' in [https://sm.alliedmods.net/new-api/entity/__raw entity.inc]).&lt;br /&gt;
&lt;br /&gt;
=How do I add color to my messages?=&lt;br /&gt;
Though the actual colors will vary depending on the mod, you can add color to any chat message using the characters &amp;lt;tt&amp;gt;0x01&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;0x08&amp;lt;/tt&amp;gt;. For example:&lt;br /&gt;
&amp;lt;pawn&amp;gt;PrintToChatAll (&amp;quot;\x01 1 .. \x02 2 .. \x03 3 .. \x04 4 .. \x05 5 .. \x06 6 .. \x07 7 .. \x08 8&amp;quot;);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example output from Left 4 Dead:&lt;br /&gt;
&lt;br /&gt;
[[Image:Left_4_Dead_Colors.png]]&lt;br /&gt;
&lt;br /&gt;
With a little experimenting, you can learn the colors for a mod. However, the meaning behind the colors is generally as follows:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x01&amp;lt;/tt&amp;gt; = Normal color&lt;br /&gt;
* &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x02&amp;lt;/tt&amp;gt; = Use team color to the end of a player's name. When used, it can be the only color used, and it must be at the start of the message.&lt;br /&gt;
* &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x03&amp;lt;/tt&amp;gt; = Team color&lt;br /&gt;
* &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x04&amp;lt;/tt&amp;gt; = Location color&lt;br /&gt;
&lt;br /&gt;
This data comes from Counter-Strike: Source.&lt;br /&gt;
&lt;br /&gt;
For CS:GO, here are some colors:&lt;br /&gt;
&amp;lt;pawn&amp;gt;PrintToChat(&amp;quot;\x011\x022\x033\x044\x055\x066\x077\x088\x099\x0AA\x0BB\x0CC\x0DD\x0EE\x0FF&amp;quot;);&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unfortunately, to use players' team colors, you must use UserMessages, because there is no way for the current SourceMod functions to know which team color to use. Here's an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;Handle hBf;&lt;br /&gt;
hBf = StartMessageOne(&amp;quot;SayText2&amp;quot;, player_to); // To send the message to all players, use StartMessageAll(&amp;quot;SayText2&amp;quot;);&lt;br /&gt;
if (hBf != null)&lt;br /&gt;
{&lt;br /&gt;
    BfWriteByte(hBf, player_from); &lt;br /&gt;
    BfWriteByte(hBf, 0); &lt;br /&gt;
    BfWriteString(hBf, &amp;quot;&amp;lt;\x03player_from team color\x01&amp;gt; My message&amp;quot;);&lt;br /&gt;
    EndMessage();&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;player_to&amp;lt;/tt&amp;gt; is the client index to send the message to (or use [https://sm.alliedmods.net/new-api/usermessages/StartMessageAll StartMessageAll()] instead of [https://sm.alliedmods.net/new-api/usermessages/StartMessageOne StartMessageOne()] to send the message to all players). &amp;lt;tt&amp;gt;player_from&amp;lt;/tt&amp;gt; is the client index of the player whose team color will be utilized in the message. The message will now look like this (assuming &amp;lt;tt&amp;gt;player_from&amp;lt;/tt&amp;gt; is on the RED team):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#AA0&amp;quot;&amp;gt;&amp;amp;lt;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#F00&amp;quot;&amp;gt;player_from team color&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color:#AA0&amp;quot;&amp;gt;&amp;amp;gt; My message&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There's another catch, however: this is only known to work in CS:S and TF2. For other mods, your mileage may vary.&lt;br /&gt;
&lt;br /&gt;
Additionally, CS:S, TF2, HL2:DM, and DoD:S all support RGB(A) hex values in chat messages with &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x07&amp;lt;/tt&amp;gt; and &amp;lt;tt style=&amp;quot;color: blue;&amp;quot;&amp;gt;0x08&amp;lt;/tt&amp;gt;, followed by a 6- or 8- char hex value (e.g., &amp;lt;tt&amp;gt;\x07ABCDEF&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;\x0801234567&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==Color Libraries==&lt;br /&gt;
There are a few libraries that can handle colors for you, so you don't have to muck with UserMessages:&lt;br /&gt;
&lt;br /&gt;
===exvel's Colors===&lt;br /&gt;
This is a simple include file, allowing easy control over chat coloring. You can grab it [http://forums.alliedmods.net/showthread.php?t=96831 on the forums].  Instead of hex codes, colors are denoted with tags, such as &amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{default}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{green}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt;, or &amp;lt;span style=&amp;quot;color: #00F;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{blue}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Here's some example usage. Note that this code assumes client 1 is in game and on the &amp;lt;span style=&amp;quot;color: #00F;&amp;quot;&amp;gt;BLU&amp;lt;/span&amp;gt; team:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;colors&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    CPrintToChatAll(&amp;quot;{green}Hello {red}World! {default}Test 1 concluded.&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    int client_on_blu_team = 1;&lt;br /&gt;
    CPrintToChatAllEx(client_on_blu_team, &amp;quot;{teamcolor}BLU team {default}says {green}hi!&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;Hello &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #F00;&amp;quot;&amp;gt;World! &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;Test 1 concluded.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: #00F;&amp;quot;&amp;gt;BLU team &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;says &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;hi!&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that to use a team color, there needs to be at least one player on that team. Otherwise, it will default to &amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{green}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===SMLib===&lt;br /&gt;
[http://forums.alliedmods.net/showthread.php?p=1398699 SMLib] is a huge collection of stock functions to keep plug-in developers from reinventing the wheel. It includes a [http://forums.alliedmods.net/showthread.php?p=1398702#post1398702 colors API] very similar to [[#exvel's Colors|exvel's]]. The benefits of SMLib are it supports shorthand color names, such as &amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{N}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt; and &amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;&amp;lt;tt&amp;gt;{G}&amp;lt;/tt&amp;gt;&amp;lt;/span&amp;gt;, and all colors are supported in its &amp;lt;tt&amp;gt;Client_PrintToChat()&amp;lt;/tt&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
Here's how to print the same thing as the above example with SMLib. Note that this code also assumes client 1 is in game and on the &amp;lt;span style=&amp;quot;color: #00F;&amp;quot;&amp;gt;BLU&amp;lt;/span&amp;gt; team:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;smlib&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
    Client_PrintToChatAll(&amp;quot;{G}Hello {R}World! {N}Test 1 concluded.&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    int client_on_blu_team = 1;&lt;br /&gt;
    Client_PrintToChatAll(client_on_blu_team, &amp;quot;{T}BLU team {N}says {G}hi!&amp;quot;);&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;Hello &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #F00;&amp;quot;&amp;gt;World! &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;Test 1 concluded.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color: #00F;&amp;quot;&amp;gt;BLU team &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #AA0;&amp;quot;&amp;gt;says &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #0F0;&amp;quot;&amp;gt;hi!&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Why do I get an &amp;quot;unknown symbol&amp;quot; error when using an SDKTools native?=&lt;br /&gt;
None of SourceMod's or SDKTools's functions are built into SourcePawn. Therefore, every time you use one of their functions, SourcePawn needs to know how to call the function. Normally, this is done using includes. Just like you would #include &amp;lt;sourcemod&amp;gt; to use SourceMod's functions, you need to:&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sdktools&amp;gt;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
to use an SDKTools native.&lt;br /&gt;
&lt;br /&gt;
=Why is Source telling me my command is an &amp;quot;Unknown command&amp;quot;?=&lt;br /&gt;
This is because you're not returning &amp;lt;tt&amp;gt;Plugin_Handled&amp;lt;/tt&amp;gt; in your callback. If you don't, SourceMod believes you didn't want the Source Engine to know the command was registered, and it handles it so.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pawn&amp;gt;public Action MyCommand(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
    // Do something...&lt;br /&gt;
    &lt;br /&gt;
    return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/pawn&amp;gt;&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Introduction_to_SourceMod_Plugins&amp;diff=11416</id>
		<title>Introduction to SourceMod Plugins</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Introduction_to_SourceMod_Plugins&amp;diff=11416"/>
		<updated>2023-03-23T13:14:42Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported? */ Add answers for ongoing development&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide will give you a basic introduction to writing a [[SourceMod]] plugin.  If you are not familiar with the SourcePawn language, it is recommended that you at least briefly read the [[Introduction to SourcePawn]] article.&lt;br /&gt;
&lt;br /&gt;
For information on compiling plugins, see [[Compiling SourceMod Plugins]]. You can use [https://forums.alliedmods.net/showthread.php?p=2693577 SPCode], [https://www.crimsoneditor.com/ Crimson Editor], [http://www.pspad.com/ PSPad], [http://www.ultraedit.com/ UltraEdit], [https://notepad-plus-plus.org/ Notepad++], [https://www.textpad.com/ TextPad], [http://sourceforge.net/projects/pawnstudio/ Pawn Studio], [https://forums.alliedmods.net/showthread.php?t=289127 BasicPawn] or any other text editor you're comfortable with to write plugins.&lt;br /&gt;
&lt;br /&gt;
=Starting from scratch=&lt;br /&gt;
Open your favorite text editor and create a new empty file. When you have an empty file you can just start writing code using the core language, however, you will not be able to use any of SourceMod features because the compiler does not know about them. This is done deliberately so it is possible to use SourcePawn outside of SourceMod. But since we are writing a SourceMod plugin, it is a good idea to enable access to SourceMod features first. This is done using &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive. It tells the compiler to &amp;quot;paste&amp;quot; the code from another file into yours.&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
How does this work? First of all, note that we enclosed file name into angle brackets. Angle brackets tell the compiler to look in the default include directory. By default, it is '''scripting/include'''. You can open it right now and see a lot of inc files there. Those are SourceMod include files that describe various functions, tags and other features available for SourceMod plugins. The files are plain-text and you are encouraged to read them. You will notice, however, that there's not much code in there, certainly not enough to implement all the great features of SourceMod, so where are they? They are implemented inside a SourceMod core which is written in C++ and is compiled into binary files which end up in '''bin''' directory. So how does your SourcePawn code and SM core link together if the compiler doesn't know about the existence of the latter? SourceMod include files are written specially, so they say that the implementation of functions is ''somewhere else''. The compiler understands that and generates a special code that says that this function call is going outside. When SourceMod loads your plugin, it inspects these bits of code and substitutes it's own internal functions instead. This is called [http://en.wikipedia.org/wiki/Dynamic_linking dynamic linking].&lt;br /&gt;
&lt;br /&gt;
=Setting up plugin info=&lt;br /&gt;
Now that we got access to SourceMod features, it is time to set up the information that will be displayed via &amp;lt;tt&amp;gt;sm plugins list&amp;lt;/tt&amp;gt; command. No one likes unnamed plugins. To do that we are going to look inside '''sourcemod.inc''' file and see the format that information should be declared. It's always helpful to look inside SM include files to find out information you don't know. There is also an [http://docs.sourcemod.net/api/ API documentation] but it can be outdated and it only has SM core files so if your plugin is going to use any third party extension or another plugin, you will have to study inc files. So, open '''sourcemod.inc''' and scroll down a bit until you see this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Plugin public information.&lt;br /&gt;
 */&lt;br /&gt;
struct Plugin&lt;br /&gt;
{&lt;br /&gt;
   public const char[] name;		/**&amp;lt; Plugin Name */&lt;br /&gt;
   public const char[] description;	/**&amp;lt; Plugin Description */&lt;br /&gt;
   public const char[] author;		/**&amp;lt; Plugin Author */&lt;br /&gt;
   public const char[] version;		/**&amp;lt; Plugin Version */&lt;br /&gt;
   public const char[] url;			/**&amp;lt; Plugin URL */&lt;br /&gt;
};&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
and this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Declare this as a struct in your plugin to expose its information.&lt;br /&gt;
 * Example:&lt;br /&gt;
 *&lt;br /&gt;
 * public Plugin myinfo =&lt;br /&gt;
 * {&lt;br /&gt;
 *    name = &amp;quot;My Plugin&amp;quot;,&lt;br /&gt;
 *    //etc&lt;br /&gt;
 * };&lt;br /&gt;
 */&lt;br /&gt;
public Plugin myinfo;&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It tells us that we need to create a global public variable &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; which must be of type &amp;lt;tt&amp;gt;Plugin&amp;lt;/tt&amp;gt; which is a struct with 5 fields which themselves are strings. It may sound complicated for a beginner but it's easy. Let's go ahead and create one:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt; keyword means that SourceMod will be able to directly access our variable. &amp;lt;tt&amp;gt;Plugin&amp;lt;/tt&amp;gt; defines a type of our variable. &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; is, obviously, a name of our variable as required by SourceMod. You see that we initialize it right away. This is the preferable way to fill out plugin info.&lt;br /&gt;
&lt;br /&gt;
After that the full code of your plugin should look like this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Getting code to run=&lt;br /&gt;
We already include SourceMod features and filled up or plugin info. We now have a perfectly well-formed plugin which can be compiled and loaded by SourceMod. However, there is one problem - it does nothing. You might be tempted to just start writing a code after &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; declaration just to see that it will not compile. SourcePawn, unlike other scripting languages like Lua, does not allow a code to be outside of functions. After reading that, you may probably want to just define some function, name it &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; probably, compile and load a plugin and see that your code never gets called. So how do we make SourceMod call our code? For this exact reason, we have forwards. Forwards are function prototypes declared by one party that can be implemented by another party as a [http://en.wikipedia.org/wiki/Callback_%28computer_programming%29 callback]. When a first party starts a forward call, all parties that have matching callbacks receive the call. SourceMod declares a plenty of interesting forwards that we can implement. As you can see, forwards are the only way to get our code executed, keep that in mind. So let's implement &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt; forward. As you may have guessed, it is called when our plugin starts. To do that, we'll have to look up the declaration of &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt;. It is declared inside '''sourcemod.inc''', a file we are already familiar with, let's find it:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Called when the plugin is fully initialized and all known external references &lt;br /&gt;
 * are resolved. This is only called once in the lifetime of the plugin, and is &lt;br /&gt;
 * paired with OnPluginEnd().&lt;br /&gt;
 *&lt;br /&gt;
 * If any run-time error is thrown during this callback, the plugin will be marked &lt;br /&gt;
 * as failed.&lt;br /&gt;
 *&lt;br /&gt;
 * It is not necessary to close any handles or remove hooks in this function.  &lt;br /&gt;
 * SourceMod guarantees that plugin shutdown automatically and correctly releases &lt;br /&gt;
 * all resources.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
forward void OnPluginStart();&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
Empty parentheses tell us that no arguments are passed inside this forward, &amp;lt;tt&amp;gt;@noreturn&amp;lt;/tt&amp;gt; inside documentation tells us that we don't have to return anything, pretty simple forward. So how to write a correct callback for it? Firstly, our callback must have the same name, so it's &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt;, secondly, our callback should have the same number of arguments, none in this case, and lastly, SourceMod needs to be able to call our callback so it needs to be &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt;. So the implementation looks like this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we can write code inside curly braces and it will be executed when our plugin starts. Let's output &amp;lt;tt&amp;gt;&amp;quot;Hello world!&amp;quot;&amp;lt;/tt&amp;gt; to server console. To do that we are going to use &amp;lt;tt&amp;gt;PrintToServer&amp;lt;/tt&amp;gt; function. It is declared inside '''console.inc''', however, we don't need to manually include '''console.inc''' because it is included automatically as part of '''sourcemod.inc'''.&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Sends a message to the server console.&lt;br /&gt;
 *&lt;br /&gt;
 * @param format		Formatting rules.&lt;br /&gt;
 * @param ...			Variable number of format parameters.&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native int PrintToServer(const char[] format, any ...);&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
As you can see, this is a native function. It is implemented inside SM core. Judging by it's arguments, we can see that it is a [[Format_Class_Functions_%28SourceMod_Scripting%29|format class function]]. However, we don't need any formatting right now, so let's just pass &amp;lt;tt&amp;gt;&amp;quot;Hello world!&amp;quot;&amp;lt;/tt&amp;gt; string as an only argument:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Hello world!&amp;quot;);&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
That's it! The full code of your plugin should look like this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Hello world!&amp;quot;);&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
Compile and load your plugin on your server and see for yourself that the message is displayed in the server console.&lt;br /&gt;
&lt;br /&gt;
=Includes=&lt;br /&gt;
Pawn requires '''include files''', much like C requires header files.  Include files list all of the structures, functions, callbacks, and tags that are available.  There are three types of include files:&lt;br /&gt;
*'''Core''' - &amp;lt;tt&amp;gt;sourcemod.inc&amp;lt;/tt&amp;gt; and anything it includes.  These are all provided by SourceMod's Core.&lt;br /&gt;
*'''Extension''' - adds a dependency against a certain extension.&lt;br /&gt;
*'''Plugin''' - adds a dependency against a certain plugin.&lt;br /&gt;
&lt;br /&gt;
Include files are loaded using the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; compiler directive.&lt;br /&gt;
&lt;br /&gt;
=Commands=&lt;br /&gt;
Our first example will be writing a simple admin command to slap a player.  We'll continue to extend this example with more features until we have a final, complete result.&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
First, let's look at what an admin command requires.  Admin commands are registered using the [https://sm.alliedmods.net/new-api/console/RegAdminCmd RegAdminCmd] function.  They require a '''name''', a '''callback function''', and '''default admin flags'''.  &lt;br /&gt;
&lt;br /&gt;
The callback function is what's invoked every time the command is used.  [https://sm.alliedmods.net/new-api/console/ConCmd Click here] to see its prototype.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we've successfully implemented a command -- though it doesn't do anything yet.  In fact, it will say &amp;quot;Unknown command&amp;quot; if you use it! This is because you're not returning Plugin_Handled in your callback. Since you haven't,  SourceMod believes you didn't want the Source Engine to know the command was registered, and it handles it so. The reason SourceMod expects your function to return Plugin_Handled is because of the Action tag you put in your function's prototype. The Action tag specifies that Command_MySlap must return one of four things. See the [https://sm.alliedmods.net/new-api/core/Action Action] enumeration in the sourcemod API to learn more about these return types and when to use them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the command will report no error, but it still won't do anything. This is because returning &amp;quot;Plugin_Handled&amp;quot; in a command callback will prevent the engine from processing the command. The engine will never even see that the command was run. This is what you will want to do if you are registering a completely new command through SourceMod.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Let's decide what the command will look like.  Let's have it act like the default &amp;lt;tt&amp;gt;sm_slap&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;pre&amp;gt;sm_myslap &amp;lt;name|#userid&amp;gt; [damage]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To implement this, we'll need a few steps:&lt;br /&gt;
*Get the input from the console.  For this we use [https://sm.alliedmods.net/new-api/console/GetCmdArg GetCmdArg()].&lt;br /&gt;
*Find a matching player.  For this we use [https://sm.alliedmods.net/new-api/helpers/FindTarget FindTarget()].&lt;br /&gt;
*Slap them.  For this we use [https://sm.alliedmods.net/new-api/sdktools_functions/SlapPlayer SlapPlayer()], which requires including &amp;lt;tt&amp;gt;sdktools&amp;lt;/tt&amp;gt;, an extension bundled with SourceMod.&lt;br /&gt;
*Respond to the admin.  For this we use [https://sm.alliedmods.net/new-api/console/ReplyToCommand ReplyToCommand()].&lt;br /&gt;
&lt;br /&gt;
Full example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
#include &amp;lt;sdktools&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0.0.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
	LoadTranslations(&amp;quot;common.phrases.txt&amp;quot;); // Required for FindTarget fail reply&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	&lt;br /&gt;
	/* By default, we set damage = 0 */&lt;br /&gt;
	int damage = 0;&lt;br /&gt;
&lt;br /&gt;
	/* Get the first argument */&lt;br /&gt;
	GetCmdArg(1, arg1, sizeof(arg1));&lt;br /&gt;
&lt;br /&gt;
	/* If there are 2 or more arguments, we set damage to&lt;br /&gt;
	 * what the user specified. If a damage isn't specified&lt;br /&gt;
	 * then it will stay zero. */&lt;br /&gt;
	if (args &amp;gt;= 2)&lt;br /&gt;
	{&lt;br /&gt;
		GetCmdArg(2, arg2, sizeof(arg2));&lt;br /&gt;
		damage = StringToInt(arg2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Try and find a matching player */&lt;br /&gt;
	int target = FindTarget(client, arg1);&lt;br /&gt;
	if (target == -1)&lt;br /&gt;
	{&lt;br /&gt;
		/* FindTarget() automatically replies with the &lt;br /&gt;
		 * failure reason and returns -1 so we know not &lt;br /&gt;
		 * to continue&lt;br /&gt;
		 */&lt;br /&gt;
		return Plugin_Handled;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	SlapPlayer(target, damage);&lt;br /&gt;
	ReplyToCommand(client, &amp;quot;[SM] You slapped %N for %d damage!&amp;quot;, target, damage);&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information on what %N and %d are, see [[Format Class Functions (SourceMod Scripting)|Format Class Functions]].  Note that you never need to unregister or remove your admin command.  When a plugin is unloaded, SourceMod cleans it up for you.&lt;br /&gt;
&lt;br /&gt;
=ConVars=&lt;br /&gt;
ConVars, also known as cvars, are global console variables in the Source engine.  They can have integer, float, or string values.  ConVar accessing is done through [[Handles (SourceMod Scripting)|Handles]].  Since ConVars are global, you do not need to close ConVar Handles (in fact, you cannot).&lt;br /&gt;
&lt;br /&gt;
The handy feature of ConVars is that they are easy for users to configure.  They can be placed in any .cfg file, such as &amp;lt;tt&amp;gt;server.cfg&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;sourcemod.cfg&amp;lt;/tt&amp;gt;.  To make this easier, SourceMod has an [https://sm.alliedmods.net/new-api/sourcemod/AutoExecConfig AutoExecConfig()] function.  This function will automatically build a default .cfg file containing all of your cvars, annotated with comments, for users.  It is highly recommended that you call this if you have customizable ConVars.&lt;br /&gt;
&lt;br /&gt;
Let's extend your example from earlier with a new ConVar.  Our ConVar will be &amp;lt;tt&amp;gt;g_cvarMySlapDamage&amp;lt;/tt&amp;gt; and will specify the default damage someone is slapped for if no damage is specified.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;ConVar g_cvarMySlapDamage = null;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
&lt;br /&gt;
	g_cvarMySlapDamage = CreateConVar(&amp;quot;sm_myslap_damage&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;Default slap damage&amp;quot;);&lt;br /&gt;
	AutoExecConfig(true, &amp;quot;plugin_myslap&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage = g_cvarMySlapDamage.IntValue;&lt;br /&gt;
&lt;br /&gt;
	/* The rest remains unchanged! */&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Showing Activity, Logging=&lt;br /&gt;
Almost all admin commands should log their activity, and some admin commands should show their activity to in-game clients.  This can be done via the [https://sm.alliedmods.net/new-api/logging/LogAction LogAction()] and [https://sm.alliedmods.net/new-api/console/ShowActivity2 ShowActivity2()] functions.  The exact functionality of ShowActivity2() is determined by the &amp;lt;tt&amp;gt;sm_show_activity&amp;lt;/tt&amp;gt; cvar.&lt;br /&gt;
&lt;br /&gt;
For example, let's rewrite the last few lines of our slap command:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
	SlapPlayer(target, damage);&lt;br /&gt;
&lt;br /&gt;
	char name[MAX_NAME_LENGTH];&lt;br /&gt;
	&lt;br /&gt;
	GetClientName(target, name, sizeof(name));&lt;br /&gt;
&lt;br /&gt;
	ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %s for %d damage!&amp;quot;, name, damage);&lt;br /&gt;
	LogAction(client, target, &amp;quot;\&amp;quot;%L\&amp;quot; slapped \&amp;quot;%L\&amp;quot; (damage %d)&amp;quot;, client, target, damage);&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Multiple Targets=&lt;br /&gt;
To fully complete our slap demonstration, let's make it support multiple targets.  SourceMod's [[Admin_Commands_%28SourceMod%29#How_to_Target|targeting system]] is quite advanced, so using it may seem complicated at first.  &lt;br /&gt;
&lt;br /&gt;
The function we use is [https://sm.alliedmods.net/new-api/commandfilters/ProcessTargetString ProcessTargetString()].  It takes in input from the console and returns a list of matching clients.  It also returns a noun that will identify either a single client or describe a list of clients.  The idea is that each client is then processed, but the activity shown to all players is only processed once.  This reduces screen spam.&lt;br /&gt;
&lt;br /&gt;
This method of target processing is used for almost every admin command in SourceMod, and in fact, FindTarget() is just a simplified version.&lt;br /&gt;
&lt;br /&gt;
Full, final example:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
#include &amp;lt;sdktools&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ConVar g_cvarMySlapDamage = null;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0.0.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
	LoadTranslations(&amp;quot;common.phrases.txt&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	g_cvarMySlapDamage = CreateConVar(&amp;quot;sm_myslap_damage&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;Default slap damage&amp;quot;);&lt;br /&gt;
	AutoExecConfig(true, &amp;quot;plugin_myslap&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage = g_cvarMySlapDamage.IntValue;&lt;br /&gt;
&lt;br /&gt;
	/* Get the first argument */&lt;br /&gt;
	GetCmdArg(1, arg1, sizeof(arg1));&lt;br /&gt;
&lt;br /&gt;
	/* If there are 2 or more arguments, and the second argument fetch &lt;br /&gt;
	 * is successful, convert it to an integer.&lt;br /&gt;
	 */&lt;br /&gt;
	if (args &amp;gt;= 2 &amp;amp;&amp;amp; GetCmdArg(2, arg2, sizeof(arg2)))&lt;br /&gt;
	{&lt;br /&gt;
		damage = StringToInt(arg2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * target_name - stores the noun identifying the target(s)&lt;br /&gt;
	 * target_list - array to store clients&lt;br /&gt;
	 * target_count - variable to store number of clients&lt;br /&gt;
	 * tn_is_ml - stores whether the noun must be translated&lt;br /&gt;
	 */&lt;br /&gt;
	char target_name[MAX_TARGET_LENGTH];&lt;br /&gt;
	int target_list[MAXPLAYERS], target_count;&lt;br /&gt;
	bool tn_is_ml;&lt;br /&gt;
&lt;br /&gt;
	if ((target_count = ProcessTargetString(&lt;br /&gt;
			arg1,&lt;br /&gt;
			client,&lt;br /&gt;
			target_list,&lt;br /&gt;
			MAXPLAYERS,&lt;br /&gt;
			COMMAND_FILTER_ALIVE, /* Only allow alive players */&lt;br /&gt;
			target_name,&lt;br /&gt;
			sizeof(target_name),&lt;br /&gt;
			tn_is_ml)) &amp;lt;= 0)&lt;br /&gt;
	{&lt;br /&gt;
		/* This function replies to the admin with a failure message */&lt;br /&gt;
		ReplyToTargetError(client, target_count);&lt;br /&gt;
		return Plugin_Handled;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (int i = 0; i &amp;lt; target_count; i++)&lt;br /&gt;
	{&lt;br /&gt;
		SlapPlayer(target_list[i], damage);&lt;br /&gt;
		LogAction(client, target_list[i], &amp;quot;\&amp;quot;%L\&amp;quot; slapped \&amp;quot;%L\&amp;quot; (damage %d)&amp;quot;, client, target_list[i], damage);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (tn_is_ml)&lt;br /&gt;
	{&lt;br /&gt;
		ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %t for %d damage!&amp;quot;, target_name, damage);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %s for %d damage!&amp;quot;, target_name, damage);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Events=&lt;br /&gt;
Events are informational notification messages passed between objects in the server.  Many are also passed from the server to the client.  They are defined in .res files under the &amp;lt;tt&amp;gt;hl2/resource&amp;lt;/tt&amp;gt; folder and &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; folders of specific mods.  For a basic listing, see [[Game Events (Source)|Source Game Events]].&lt;br /&gt;
&lt;br /&gt;
It is important to note a few concepts about events:&lt;br /&gt;
*They are almost always informational.  That is, blocking &amp;lt;tt&amp;gt;player_death&amp;lt;/tt&amp;gt; will not stop a player from dying.  It may block a HUD or console message or something else minor.&lt;br /&gt;
*They almost always use userids instead of client indexes.&lt;br /&gt;
*Just because it is in a resource file does not mean it is ever called, or works the way you expect it to.  Mods are notorious for not properly documenting their event functionality.&lt;br /&gt;
&lt;br /&gt;
An example of finding when a player dies:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
   HookEvent(&amp;quot;player_death&amp;quot;, Event_PlayerDeath);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)&lt;br /&gt;
{&lt;br /&gt;
   int victim_id = event.GetInt(&amp;quot;userid&amp;quot;);&lt;br /&gt;
   int attacker_id = event.GetInt(&amp;quot;attacker&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
   int victim = GetClientOfUserId(victim_id);&lt;br /&gt;
   int attacker = GetClientOfUserId(attacker_id);&lt;br /&gt;
&lt;br /&gt;
   /* CODE */&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Callback Orders and Pairing=&lt;br /&gt;
SourceMod has a number of builtin callbacks about the state of the server and plugin.  Some of these are paired in special ways which can confuse users.&lt;br /&gt;
&lt;br /&gt;
==Pairing==&lt;br /&gt;
'''Pairing''' is SourceMod terminology.  Examples of it are:&lt;br /&gt;
*OnMapEnd() cannot be called without an OnMapStart(), and if OnMapStart() is called, it cannot be called again without an OnMapEnd().&lt;br /&gt;
*OnClientConnected(N) for a given client N will only be called once until an OnClientDisconnected(N) for the same client N is called (which is guaranteed to happen).&lt;br /&gt;
&lt;br /&gt;
There is a formal definition of SourceMod's pairing.  For two functions X and Y, both with input A, the following conditions hold:&lt;br /&gt;
*If X is invoked with input A, it cannot be invoked again with the same input unless Y is called with input A.&lt;br /&gt;
*If X is invoked with input A, it is guaranteed that Y will, at some point, be called with input A.&lt;br /&gt;
*Y cannot be invoked with any input A unless X was called first with input A.&lt;br /&gt;
*The relationship is described as, &amp;quot;X is paired with Y,&amp;quot; and &amp;quot;Y is paired to X.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==General Callbacks==&lt;br /&gt;
These callbacks are listed in the order they are called, in the lifetime of a plugin and the server.&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=AskPluginLoad2}} - Called once, immediately after the plugin is loaded from the disk.  This function can be used to stop a plugin from loading and return a custom error message; return APLRes_Failure and use strcopy on to replace the error string.  All CreateNative and RegPluginLibrary calls should be done here.  &lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnPluginStart}} - Called once, after the plugin has been fully initialized and can proceed to load.  Any run-time errors in this function will cause the plugin to fail to load.  '''This is paired with OnPluginEnd()'''.&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnAllPluginsLoaded}} - Called once, after all non-late loaded plugins have called OnPluginStart.  &lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnMapStart}} - Called every time the map loads.  If the plugin is loaded late, and the map has already started, this function is called anyway after load, in order to preserve pairing.  '''This function is paired with OnMapEnd().'''&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnConfigsExecuted}} - Called once per map-change after &amp;lt;tt&amp;gt;servercfgfile&amp;lt;/tt&amp;gt; (usually &amp;lt;tt&amp;gt;server.cfg&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;sourcemod.cfg&amp;lt;/tt&amp;gt;, and all plugin config files have finished executing.  If a plugin is loaded after this has happened, the callback is called anyway, in order to preserve pairing.  '''This function is paired with OnMapEnd().'''&lt;br /&gt;
*At this point, most game callbacks can occur, such as events and callbacks involving clients (or other things, like OnGameFrame).&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnMapEnd}} - Called when the map is about to end.  At this point, all clients are disconnected, but &amp;lt;tt&amp;gt;TIMER_NO_MAPCHANGE&amp;lt;/tt&amp;gt; timers are not yet destroyed.  '''This function is paired to OnMapStart().'''&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnPluginEnd}} - Called once, immediately before the plugin is unloaded.  '''This function is paired to OnPluginStart().'''&lt;br /&gt;
&lt;br /&gt;
==Client Callbacks==&lt;br /&gt;
These callbacks are listed in no specific order, however, their documentation holds for both fake and real clients.&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientConnect}} - Called when a player initiates a connection.  You can block a player from connecting by returning &amp;lt;code&amp;gt;Plugin_Stop&amp;lt;/code&amp;gt; and setting rejectmsg to an error message.&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientConnected}} - Called after a player connects. Signifies that the player is connected and {{SourceMod API|file=clients|function=IsClientConnected}} will return true. '''This is paired with &amp;lt;code&amp;gt;OnClientDisconnect&amp;lt;/code&amp;gt; for successful connections only.'''&lt;br /&gt;
*{{SourceMod API|file=clients|function=OnClientAuthorized}} - Called when a player gets a Steam ID.  It is important to note that this may never be called.  It may occur any time in between &amp;lt;code&amp;gt;OnClientConnected&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;OnClientPreAdminCheck&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;OnClientDisconnect&amp;lt;/code&amp;gt;.  Do not rely on it unless you are writing something that needs Steam IDs, and even then you should use &amp;lt;code&amp;gt;OnClientPostAdminCheck&amp;lt;/code&amp;gt;.&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientPutInServer}} - Signifies that the player is fully in-game and {{SourceMod API|file=clients|function=IsClientInGame}} will return true.&lt;br /&gt;
** If you want to check if the player is in-game, you just need to call this; {{SourceMod API|file=clients|function=IsClientConnected}} will also be true if this is (but not the other way around - a player may be connected but not in-game yet).&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientPostAdminCheck}} - Called after the player is '''both authorized and in-game'''.  This is the best callback for checking administrative access after connect.&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientDisconnect}} - Called when a player's disconnection starts.  '''This is paired to &amp;lt;code&amp;gt;OnClientConnected&amp;lt;/code&amp;gt;.'''&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientDisconnect_Post}} - Called when a player's disconnection ends.  '''This is paired to &amp;lt;code&amp;gt;OnClientConnected&amp;lt;/code&amp;gt;.'''&lt;br /&gt;
&lt;br /&gt;
=Frequently Asked Questions=&lt;br /&gt;
==Are plugins reloaded every mapchange?==&lt;br /&gt;
Plugins, by default, are not reloaded on mapchange unless their timestamp changes.  This is a feature so plugin authors have more flexibility with the state of their plugins.  &lt;br /&gt;
&lt;br /&gt;
==Do I need to call CloseHandle in OnPluginEnd?==&lt;br /&gt;
No.  SourceMod automatically closes your Handles when your plugin is unloaded, in order to prevent memory errors.&lt;br /&gt;
&lt;br /&gt;
==Do I need to #include every individual .inc?==&lt;br /&gt;
No.  &amp;lt;tt&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/tt&amp;gt; will give you 95% of the .incs.  Similarly, &amp;lt;tt&amp;gt;#include &amp;lt;sdktools&amp;gt;&amp;lt;/tt&amp;gt; includes everything starting with &amp;lt;sdktools&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Why don't some events fire?==&lt;br /&gt;
There is no guarantee that events will fire.  The event listing is not a specification, it is a list of the events that a game is capable of firing.  Whether the game actually fires them is up to Valve or the developer.&lt;br /&gt;
&lt;br /&gt;
==Do I need to CloseHandle timers?==&lt;br /&gt;
No.  In fact, doing so may cause errors.  Timers naturally die on their own unless they are infinite timers, in which case you can use KillTimer() or die gracefully by returning &amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt; in the callback.&lt;br /&gt;
&lt;br /&gt;
==Are clients disconnected on mapchange?==&lt;br /&gt;
All clients are fully disconnected before the map changes.  They are all reconnected after the next map starts.&lt;br /&gt;
&lt;br /&gt;
If you only want to detect when a client initially connects or leaves your server, hook the [[Generic Source Server Events#player_connect|player_connect]] or [[Generic Source Server Events#player_disconnect|player_disconnect]] events respectively.&lt;br /&gt;
&lt;br /&gt;
==Why am I getting &amp;quot;function prototypes do not match&amp;quot; errors?==&lt;br /&gt;
When you see this error, you'll most likely find that the issue comes from any callback functions referenced in the line(s) that are causing the error.&lt;br /&gt;
&lt;br /&gt;
When you call a function that takes another function as a callback, the callback function must be declared with the correct number of parameter and return types.&lt;br /&gt;
&lt;br /&gt;
For example, [https://sm.alliedmods.net/new-api/console/RegConsoleCmd &amp;lt;tt&amp;gt;RegConsoleCommand&amp;lt;/tt&amp;gt;] must be called with a callback that has with the exact arguments and return type as specified by the [https://sm.alliedmods.net/new-api/console/ConCmd &amp;lt;tt&amp;gt;ConCmd&amp;lt;/tt&amp;gt;] definition.&lt;br /&gt;
&lt;br /&gt;
==When do I need to manually unhook things?==&lt;br /&gt;
You only need to do so when you do not want the callback to fire anymore while the plugin is running.  SourceMod itself, as well as extensions such as SDKHooks, unhooks entities and players when they are removed and disconnected, respectively.  Everything a plugin hooks is unhooked when it is unloaded.&lt;br /&gt;
&lt;br /&gt;
== Why am I seeing references to &amp;lt;tt&amp;gt;STEAM_ID_STOP_IGNORING_RETVALS&amp;lt;/tt&amp;gt;? ==&lt;br /&gt;
When {{SourceMod API|file=clients|function=GetClientAuthId}} is called and returns &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt;, the buffer that should have the client's auth id is populated with &amp;lt;tt&amp;gt;STEAM_ID_STOP_IGNORING_RETVALS&amp;lt;/tt&amp;gt;, both to clear the previous contents of the buffer (thereby preventing accidental reuse of old values) and to inform the developer to stop ignoring the return value of the &amp;lt;code&amp;gt;GetClientAuthId&amp;lt;/code&amp;gt; call.&lt;br /&gt;
&lt;br /&gt;
== Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported? ==&lt;br /&gt;
The engine already exists; Metamod:Source works to some extent.  Further reverse engineering efforts are required to get Metamod:Source in a stable state before work can even start on SourceMod.&lt;br /&gt;
&lt;br /&gt;
No decision has been made yet on if development will be focused on bringing SourceMod to Source 2, on creating a successor scripting ecosystem much like SourceMod was to [[AMX Mod X]], or on extending VScript functionality.&lt;br /&gt;
&lt;br /&gt;
It's safe to say that SourceMod will currently not work on the day of release for any games powered by Source 2.&lt;br /&gt;
&lt;br /&gt;
Notes as of the initial limited testing phase for Counter-Strike 2:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;-dedicated&amp;lt;/code&amp;gt; allows for the creation of listen servers.&lt;br /&gt;
* The VSP plugin / VDF loading capabilities have been removed.  [[Installing_Metamod:Source#GameInfo|Metamod:Source needs to be loaded as a GameDLL.]]&lt;br /&gt;
&lt;br /&gt;
Keep in mind that this is an ongoing development; nothing is ready for public use yet.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
For further reading, see the &amp;quot;Scripting&amp;quot; section at the [http://docs.sourcemod.net/ SourceMod Documentation], as well as [https://wiki.alliedmods.net/Scripting_FAQ_(SourceMod) Yak's FAQs on Scripting].&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Introduction_to_SourceMod_Plugins&amp;diff=11415</id>
		<title>Introduction to SourceMod Plugins</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Introduction_to_SourceMod_Plugins&amp;diff=11415"/>
		<updated>2023-03-13T16:54:03Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported? */ S2 is already released; reword to specifically mention game releases&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide will give you a basic introduction to writing a [[SourceMod]] plugin.  If you are not familiar with the SourcePawn language, it is recommended that you at least briefly read the [[Introduction to SourcePawn]] article.&lt;br /&gt;
&lt;br /&gt;
For information on compiling plugins, see [[Compiling SourceMod Plugins]]. You can use [https://forums.alliedmods.net/showthread.php?p=2693577 SPCode], [https://www.crimsoneditor.com/ Crimson Editor], [http://www.pspad.com/ PSPad], [http://www.ultraedit.com/ UltraEdit], [https://notepad-plus-plus.org/ Notepad++], [https://www.textpad.com/ TextPad], [http://sourceforge.net/projects/pawnstudio/ Pawn Studio], [https://forums.alliedmods.net/showthread.php?t=289127 BasicPawn] or any other text editor you're comfortable with to write plugins.&lt;br /&gt;
&lt;br /&gt;
=Starting from scratch=&lt;br /&gt;
Open your favorite text editor and create a new empty file. When you have an empty file you can just start writing code using the core language, however, you will not be able to use any of SourceMod features because the compiler does not know about them. This is done deliberately so it is possible to use SourcePawn outside of SourceMod. But since we are writing a SourceMod plugin, it is a good idea to enable access to SourceMod features first. This is done using &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive. It tells the compiler to &amp;quot;paste&amp;quot; the code from another file into yours.&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
How does this work? First of all, note that we enclosed file name into angle brackets. Angle brackets tell the compiler to look in the default include directory. By default, it is '''scripting/include'''. You can open it right now and see a lot of inc files there. Those are SourceMod include files that describe various functions, tags and other features available for SourceMod plugins. The files are plain-text and you are encouraged to read them. You will notice, however, that there's not much code in there, certainly not enough to implement all the great features of SourceMod, so where are they? They are implemented inside a SourceMod core which is written in C++ and is compiled into binary files which end up in '''bin''' directory. So how does your SourcePawn code and SM core link together if the compiler doesn't know about the existence of the latter? SourceMod include files are written specially, so they say that the implementation of functions is ''somewhere else''. The compiler understands that and generates a special code that says that this function call is going outside. When SourceMod loads your plugin, it inspects these bits of code and substitutes it's own internal functions instead. This is called [http://en.wikipedia.org/wiki/Dynamic_linking dynamic linking].&lt;br /&gt;
&lt;br /&gt;
=Setting up plugin info=&lt;br /&gt;
Now that we got access to SourceMod features, it is time to set up the information that will be displayed via &amp;lt;tt&amp;gt;sm plugins list&amp;lt;/tt&amp;gt; command. No one likes unnamed plugins. To do that we are going to look inside '''sourcemod.inc''' file and see the format that information should be declared. It's always helpful to look inside SM include files to find out information you don't know. There is also an [http://docs.sourcemod.net/api/ API documentation] but it can be outdated and it only has SM core files so if your plugin is going to use any third party extension or another plugin, you will have to study inc files. So, open '''sourcemod.inc''' and scroll down a bit until you see this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Plugin public information.&lt;br /&gt;
 */&lt;br /&gt;
struct Plugin&lt;br /&gt;
{&lt;br /&gt;
   public const char[] name;		/**&amp;lt; Plugin Name */&lt;br /&gt;
   public const char[] description;	/**&amp;lt; Plugin Description */&lt;br /&gt;
   public const char[] author;		/**&amp;lt; Plugin Author */&lt;br /&gt;
   public const char[] version;		/**&amp;lt; Plugin Version */&lt;br /&gt;
   public const char[] url;			/**&amp;lt; Plugin URL */&lt;br /&gt;
};&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
and this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Declare this as a struct in your plugin to expose its information.&lt;br /&gt;
 * Example:&lt;br /&gt;
 *&lt;br /&gt;
 * public Plugin myinfo =&lt;br /&gt;
 * {&lt;br /&gt;
 *    name = &amp;quot;My Plugin&amp;quot;,&lt;br /&gt;
 *    //etc&lt;br /&gt;
 * };&lt;br /&gt;
 */&lt;br /&gt;
public Plugin myinfo;&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It tells us that we need to create a global public variable &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; which must be of type &amp;lt;tt&amp;gt;Plugin&amp;lt;/tt&amp;gt; which is a struct with 5 fields which themselves are strings. It may sound complicated for a beginner but it's easy. Let's go ahead and create one:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt; keyword means that SourceMod will be able to directly access our variable. &amp;lt;tt&amp;gt;Plugin&amp;lt;/tt&amp;gt; defines a type of our variable. &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; is, obviously, a name of our variable as required by SourceMod. You see that we initialize it right away. This is the preferable way to fill out plugin info.&lt;br /&gt;
&lt;br /&gt;
After that the full code of your plugin should look like this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Getting code to run=&lt;br /&gt;
We already include SourceMod features and filled up or plugin info. We now have a perfectly well-formed plugin which can be compiled and loaded by SourceMod. However, there is one problem - it does nothing. You might be tempted to just start writing a code after &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; declaration just to see that it will not compile. SourcePawn, unlike other scripting languages like Lua, does not allow a code to be outside of functions. After reading that, you may probably want to just define some function, name it &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; probably, compile and load a plugin and see that your code never gets called. So how do we make SourceMod call our code? For this exact reason, we have forwards. Forwards are function prototypes declared by one party that can be implemented by another party as a [http://en.wikipedia.org/wiki/Callback_%28computer_programming%29 callback]. When a first party starts a forward call, all parties that have matching callbacks receive the call. SourceMod declares a plenty of interesting forwards that we can implement. As you can see, forwards are the only way to get our code executed, keep that in mind. So let's implement &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt; forward. As you may have guessed, it is called when our plugin starts. To do that, we'll have to look up the declaration of &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt;. It is declared inside '''sourcemod.inc''', a file we are already familiar with, let's find it:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Called when the plugin is fully initialized and all known external references &lt;br /&gt;
 * are resolved. This is only called once in the lifetime of the plugin, and is &lt;br /&gt;
 * paired with OnPluginEnd().&lt;br /&gt;
 *&lt;br /&gt;
 * If any run-time error is thrown during this callback, the plugin will be marked &lt;br /&gt;
 * as failed.&lt;br /&gt;
 *&lt;br /&gt;
 * It is not necessary to close any handles or remove hooks in this function.  &lt;br /&gt;
 * SourceMod guarantees that plugin shutdown automatically and correctly releases &lt;br /&gt;
 * all resources.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
forward void OnPluginStart();&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
Empty parentheses tell us that no arguments are passed inside this forward, &amp;lt;tt&amp;gt;@noreturn&amp;lt;/tt&amp;gt; inside documentation tells us that we don't have to return anything, pretty simple forward. So how to write a correct callback for it? Firstly, our callback must have the same name, so it's &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt;, secondly, our callback should have the same number of arguments, none in this case, and lastly, SourceMod needs to be able to call our callback so it needs to be &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt;. So the implementation looks like this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we can write code inside curly braces and it will be executed when our plugin starts. Let's output &amp;lt;tt&amp;gt;&amp;quot;Hello world!&amp;quot;&amp;lt;/tt&amp;gt; to server console. To do that we are going to use &amp;lt;tt&amp;gt;PrintToServer&amp;lt;/tt&amp;gt; function. It is declared inside '''console.inc''', however, we don't need to manually include '''console.inc''' because it is included automatically as part of '''sourcemod.inc'''.&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Sends a message to the server console.&lt;br /&gt;
 *&lt;br /&gt;
 * @param format		Formatting rules.&lt;br /&gt;
 * @param ...			Variable number of format parameters.&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native int PrintToServer(const char[] format, any ...);&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
As you can see, this is a native function. It is implemented inside SM core. Judging by it's arguments, we can see that it is a [[Format_Class_Functions_%28SourceMod_Scripting%29|format class function]]. However, we don't need any formatting right now, so let's just pass &amp;lt;tt&amp;gt;&amp;quot;Hello world!&amp;quot;&amp;lt;/tt&amp;gt; string as an only argument:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Hello world!&amp;quot;);&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
That's it! The full code of your plugin should look like this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Hello world!&amp;quot;);&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
Compile and load your plugin on your server and see for yourself that the message is displayed in the server console.&lt;br /&gt;
&lt;br /&gt;
=Includes=&lt;br /&gt;
Pawn requires '''include files''', much like C requires header files.  Include files list all of the structures, functions, callbacks, and tags that are available.  There are three types of include files:&lt;br /&gt;
*'''Core''' - &amp;lt;tt&amp;gt;sourcemod.inc&amp;lt;/tt&amp;gt; and anything it includes.  These are all provided by SourceMod's Core.&lt;br /&gt;
*'''Extension''' - adds a dependency against a certain extension.&lt;br /&gt;
*'''Plugin''' - adds a dependency against a certain plugin.&lt;br /&gt;
&lt;br /&gt;
Include files are loaded using the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; compiler directive.&lt;br /&gt;
&lt;br /&gt;
=Commands=&lt;br /&gt;
Our first example will be writing a simple admin command to slap a player.  We'll continue to extend this example with more features until we have a final, complete result.&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
First, let's look at what an admin command requires.  Admin commands are registered using the [https://sm.alliedmods.net/new-api/console/RegAdminCmd RegAdminCmd] function.  They require a '''name''', a '''callback function''', and '''default admin flags'''.  &lt;br /&gt;
&lt;br /&gt;
The callback function is what's invoked every time the command is used.  [https://sm.alliedmods.net/new-api/console/ConCmd Click here] to see its prototype.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we've successfully implemented a command -- though it doesn't do anything yet.  In fact, it will say &amp;quot;Unknown command&amp;quot; if you use it! This is because you're not returning Plugin_Handled in your callback. Since you haven't,  SourceMod believes you didn't want the Source Engine to know the command was registered, and it handles it so. The reason SourceMod expects your function to return Plugin_Handled is because of the Action tag you put in your function's prototype. The Action tag specifies that Command_MySlap must return one of four things. See the [https://sm.alliedmods.net/new-api/core/Action Action] enumeration in the sourcemod API to learn more about these return types and when to use them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the command will report no error, but it still won't do anything. This is because returning &amp;quot;Plugin_Handled&amp;quot; in a command callback will prevent the engine from processing the command. The engine will never even see that the command was run. This is what you will want to do if you are registering a completely new command through SourceMod.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Let's decide what the command will look like.  Let's have it act like the default &amp;lt;tt&amp;gt;sm_slap&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;pre&amp;gt;sm_myslap &amp;lt;name|#userid&amp;gt; [damage]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To implement this, we'll need a few steps:&lt;br /&gt;
*Get the input from the console.  For this we use [https://sm.alliedmods.net/new-api/console/GetCmdArg GetCmdArg()].&lt;br /&gt;
*Find a matching player.  For this we use [https://sm.alliedmods.net/new-api/helpers/FindTarget FindTarget()].&lt;br /&gt;
*Slap them.  For this we use [https://sm.alliedmods.net/new-api/sdktools_functions/SlapPlayer SlapPlayer()], which requires including &amp;lt;tt&amp;gt;sdktools&amp;lt;/tt&amp;gt;, an extension bundled with SourceMod.&lt;br /&gt;
*Respond to the admin.  For this we use [https://sm.alliedmods.net/new-api/console/ReplyToCommand ReplyToCommand()].&lt;br /&gt;
&lt;br /&gt;
Full example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
#include &amp;lt;sdktools&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0.0.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
	LoadTranslations(&amp;quot;common.phrases.txt&amp;quot;); // Required for FindTarget fail reply&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	&lt;br /&gt;
	/* By default, we set damage = 0 */&lt;br /&gt;
	int damage = 0;&lt;br /&gt;
&lt;br /&gt;
	/* Get the first argument */&lt;br /&gt;
	GetCmdArg(1, arg1, sizeof(arg1));&lt;br /&gt;
&lt;br /&gt;
	/* If there are 2 or more arguments, we set damage to&lt;br /&gt;
	 * what the user specified. If a damage isn't specified&lt;br /&gt;
	 * then it will stay zero. */&lt;br /&gt;
	if (args &amp;gt;= 2)&lt;br /&gt;
	{&lt;br /&gt;
		GetCmdArg(2, arg2, sizeof(arg2));&lt;br /&gt;
		damage = StringToInt(arg2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Try and find a matching player */&lt;br /&gt;
	int target = FindTarget(client, arg1);&lt;br /&gt;
	if (target == -1)&lt;br /&gt;
	{&lt;br /&gt;
		/* FindTarget() automatically replies with the &lt;br /&gt;
		 * failure reason and returns -1 so we know not &lt;br /&gt;
		 * to continue&lt;br /&gt;
		 */&lt;br /&gt;
		return Plugin_Handled;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	SlapPlayer(target, damage);&lt;br /&gt;
	ReplyToCommand(client, &amp;quot;[SM] You slapped %N for %d damage!&amp;quot;, target, damage);&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information on what %N and %d are, see [[Format Class Functions (SourceMod Scripting)|Format Class Functions]].  Note that you never need to unregister or remove your admin command.  When a plugin is unloaded, SourceMod cleans it up for you.&lt;br /&gt;
&lt;br /&gt;
=ConVars=&lt;br /&gt;
ConVars, also known as cvars, are global console variables in the Source engine.  They can have integer, float, or string values.  ConVar accessing is done through [[Handles (SourceMod Scripting)|Handles]].  Since ConVars are global, you do not need to close ConVar Handles (in fact, you cannot).&lt;br /&gt;
&lt;br /&gt;
The handy feature of ConVars is that they are easy for users to configure.  They can be placed in any .cfg file, such as &amp;lt;tt&amp;gt;server.cfg&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;sourcemod.cfg&amp;lt;/tt&amp;gt;.  To make this easier, SourceMod has an [https://sm.alliedmods.net/new-api/sourcemod/AutoExecConfig AutoExecConfig()] function.  This function will automatically build a default .cfg file containing all of your cvars, annotated with comments, for users.  It is highly recommended that you call this if you have customizable ConVars.&lt;br /&gt;
&lt;br /&gt;
Let's extend your example from earlier with a new ConVar.  Our ConVar will be &amp;lt;tt&amp;gt;g_cvarMySlapDamage&amp;lt;/tt&amp;gt; and will specify the default damage someone is slapped for if no damage is specified.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;ConVar g_cvarMySlapDamage = null;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
&lt;br /&gt;
	g_cvarMySlapDamage = CreateConVar(&amp;quot;sm_myslap_damage&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;Default slap damage&amp;quot;);&lt;br /&gt;
	AutoExecConfig(true, &amp;quot;plugin_myslap&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage = g_cvarMySlapDamage.IntValue;&lt;br /&gt;
&lt;br /&gt;
	/* The rest remains unchanged! */&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Showing Activity, Logging=&lt;br /&gt;
Almost all admin commands should log their activity, and some admin commands should show their activity to in-game clients.  This can be done via the [https://sm.alliedmods.net/new-api/logging/LogAction LogAction()] and [https://sm.alliedmods.net/new-api/console/ShowActivity2 ShowActivity2()] functions.  The exact functionality of ShowActivity2() is determined by the &amp;lt;tt&amp;gt;sm_show_activity&amp;lt;/tt&amp;gt; cvar.&lt;br /&gt;
&lt;br /&gt;
For example, let's rewrite the last few lines of our slap command:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
	SlapPlayer(target, damage);&lt;br /&gt;
&lt;br /&gt;
	char name[MAX_NAME_LENGTH];&lt;br /&gt;
	&lt;br /&gt;
	GetClientName(target, name, sizeof(name));&lt;br /&gt;
&lt;br /&gt;
	ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %s for %d damage!&amp;quot;, name, damage);&lt;br /&gt;
	LogAction(client, target, &amp;quot;\&amp;quot;%L\&amp;quot; slapped \&amp;quot;%L\&amp;quot; (damage %d)&amp;quot;, client, target, damage);&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Multiple Targets=&lt;br /&gt;
To fully complete our slap demonstration, let's make it support multiple targets.  SourceMod's [[Admin_Commands_%28SourceMod%29#How_to_Target|targeting system]] is quite advanced, so using it may seem complicated at first.  &lt;br /&gt;
&lt;br /&gt;
The function we use is [https://sm.alliedmods.net/new-api/commandfilters/ProcessTargetString ProcessTargetString()].  It takes in input from the console and returns a list of matching clients.  It also returns a noun that will identify either a single client or describe a list of clients.  The idea is that each client is then processed, but the activity shown to all players is only processed once.  This reduces screen spam.&lt;br /&gt;
&lt;br /&gt;
This method of target processing is used for almost every admin command in SourceMod, and in fact, FindTarget() is just a simplified version.&lt;br /&gt;
&lt;br /&gt;
Full, final example:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
#include &amp;lt;sdktools&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ConVar g_cvarMySlapDamage = null;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0.0.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
	LoadTranslations(&amp;quot;common.phrases.txt&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	g_cvarMySlapDamage = CreateConVar(&amp;quot;sm_myslap_damage&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;Default slap damage&amp;quot;);&lt;br /&gt;
	AutoExecConfig(true, &amp;quot;plugin_myslap&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage = g_cvarMySlapDamage.IntValue;&lt;br /&gt;
&lt;br /&gt;
	/* Get the first argument */&lt;br /&gt;
	GetCmdArg(1, arg1, sizeof(arg1));&lt;br /&gt;
&lt;br /&gt;
	/* If there are 2 or more arguments, and the second argument fetch &lt;br /&gt;
	 * is successful, convert it to an integer.&lt;br /&gt;
	 */&lt;br /&gt;
	if (args &amp;gt;= 2 &amp;amp;&amp;amp; GetCmdArg(2, arg2, sizeof(arg2)))&lt;br /&gt;
	{&lt;br /&gt;
		damage = StringToInt(arg2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * target_name - stores the noun identifying the target(s)&lt;br /&gt;
	 * target_list - array to store clients&lt;br /&gt;
	 * target_count - variable to store number of clients&lt;br /&gt;
	 * tn_is_ml - stores whether the noun must be translated&lt;br /&gt;
	 */&lt;br /&gt;
	char target_name[MAX_TARGET_LENGTH];&lt;br /&gt;
	int target_list[MAXPLAYERS], target_count;&lt;br /&gt;
	bool tn_is_ml;&lt;br /&gt;
&lt;br /&gt;
	if ((target_count = ProcessTargetString(&lt;br /&gt;
			arg1,&lt;br /&gt;
			client,&lt;br /&gt;
			target_list,&lt;br /&gt;
			MAXPLAYERS,&lt;br /&gt;
			COMMAND_FILTER_ALIVE, /* Only allow alive players */&lt;br /&gt;
			target_name,&lt;br /&gt;
			sizeof(target_name),&lt;br /&gt;
			tn_is_ml)) &amp;lt;= 0)&lt;br /&gt;
	{&lt;br /&gt;
		/* This function replies to the admin with a failure message */&lt;br /&gt;
		ReplyToTargetError(client, target_count);&lt;br /&gt;
		return Plugin_Handled;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (int i = 0; i &amp;lt; target_count; i++)&lt;br /&gt;
	{&lt;br /&gt;
		SlapPlayer(target_list[i], damage);&lt;br /&gt;
		LogAction(client, target_list[i], &amp;quot;\&amp;quot;%L\&amp;quot; slapped \&amp;quot;%L\&amp;quot; (damage %d)&amp;quot;, client, target_list[i], damage);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (tn_is_ml)&lt;br /&gt;
	{&lt;br /&gt;
		ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %t for %d damage!&amp;quot;, target_name, damage);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %s for %d damage!&amp;quot;, target_name, damage);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Events=&lt;br /&gt;
Events are informational notification messages passed between objects in the server.  Many are also passed from the server to the client.  They are defined in .res files under the &amp;lt;tt&amp;gt;hl2/resource&amp;lt;/tt&amp;gt; folder and &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; folders of specific mods.  For a basic listing, see [[Game Events (Source)|Source Game Events]].&lt;br /&gt;
&lt;br /&gt;
It is important to note a few concepts about events:&lt;br /&gt;
*They are almost always informational.  That is, blocking &amp;lt;tt&amp;gt;player_death&amp;lt;/tt&amp;gt; will not stop a player from dying.  It may block a HUD or console message or something else minor.&lt;br /&gt;
*They almost always use userids instead of client indexes.&lt;br /&gt;
*Just because it is in a resource file does not mean it is ever called, or works the way you expect it to.  Mods are notorious for not properly documenting their event functionality.&lt;br /&gt;
&lt;br /&gt;
An example of finding when a player dies:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
   HookEvent(&amp;quot;player_death&amp;quot;, Event_PlayerDeath);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)&lt;br /&gt;
{&lt;br /&gt;
   int victim_id = event.GetInt(&amp;quot;userid&amp;quot;);&lt;br /&gt;
   int attacker_id = event.GetInt(&amp;quot;attacker&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
   int victim = GetClientOfUserId(victim_id);&lt;br /&gt;
   int attacker = GetClientOfUserId(attacker_id);&lt;br /&gt;
&lt;br /&gt;
   /* CODE */&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Callback Orders and Pairing=&lt;br /&gt;
SourceMod has a number of builtin callbacks about the state of the server and plugin.  Some of these are paired in special ways which can confuse users.&lt;br /&gt;
&lt;br /&gt;
==Pairing==&lt;br /&gt;
'''Pairing''' is SourceMod terminology.  Examples of it are:&lt;br /&gt;
*OnMapEnd() cannot be called without an OnMapStart(), and if OnMapStart() is called, it cannot be called again without an OnMapEnd().&lt;br /&gt;
*OnClientConnected(N) for a given client N will only be called once until an OnClientDisconnected(N) for the same client N is called (which is guaranteed to happen).&lt;br /&gt;
&lt;br /&gt;
There is a formal definition of SourceMod's pairing.  For two functions X and Y, both with input A, the following conditions hold:&lt;br /&gt;
*If X is invoked with input A, it cannot be invoked again with the same input unless Y is called with input A.&lt;br /&gt;
*If X is invoked with input A, it is guaranteed that Y will, at some point, be called with input A.&lt;br /&gt;
*Y cannot be invoked with any input A unless X was called first with input A.&lt;br /&gt;
*The relationship is described as, &amp;quot;X is paired with Y,&amp;quot; and &amp;quot;Y is paired to X.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==General Callbacks==&lt;br /&gt;
These callbacks are listed in the order they are called, in the lifetime of a plugin and the server.&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=AskPluginLoad2}} - Called once, immediately after the plugin is loaded from the disk.  This function can be used to stop a plugin from loading and return a custom error message; return APLRes_Failure and use strcopy on to replace the error string.  All CreateNative and RegPluginLibrary calls should be done here.  &lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnPluginStart}} - Called once, after the plugin has been fully initialized and can proceed to load.  Any run-time errors in this function will cause the plugin to fail to load.  '''This is paired with OnPluginEnd()'''.&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnAllPluginsLoaded}} - Called once, after all non-late loaded plugins have called OnPluginStart.  &lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnMapStart}} - Called every time the map loads.  If the plugin is loaded late, and the map has already started, this function is called anyway after load, in order to preserve pairing.  '''This function is paired with OnMapEnd().'''&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnConfigsExecuted}} - Called once per map-change after &amp;lt;tt&amp;gt;servercfgfile&amp;lt;/tt&amp;gt; (usually &amp;lt;tt&amp;gt;server.cfg&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;sourcemod.cfg&amp;lt;/tt&amp;gt;, and all plugin config files have finished executing.  If a plugin is loaded after this has happened, the callback is called anyway, in order to preserve pairing.  '''This function is paired with OnMapEnd().'''&lt;br /&gt;
*At this point, most game callbacks can occur, such as events and callbacks involving clients (or other things, like OnGameFrame).&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnMapEnd}} - Called when the map is about to end.  At this point, all clients are disconnected, but &amp;lt;tt&amp;gt;TIMER_NO_MAPCHANGE&amp;lt;/tt&amp;gt; timers are not yet destroyed.  '''This function is paired to OnMapStart().'''&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnPluginEnd}} - Called once, immediately before the plugin is unloaded.  '''This function is paired to OnPluginStart().'''&lt;br /&gt;
&lt;br /&gt;
==Client Callbacks==&lt;br /&gt;
These callbacks are listed in no specific order, however, their documentation holds for both fake and real clients.&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientConnect}} - Called when a player initiates a connection.  You can block a player from connecting by returning &amp;lt;code&amp;gt;Plugin_Stop&amp;lt;/code&amp;gt; and setting rejectmsg to an error message.&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientConnected}} - Called after a player connects. Signifies that the player is connected and {{SourceMod API|file=clients|function=IsClientConnected}} will return true. '''This is paired with &amp;lt;code&amp;gt;OnClientDisconnect&amp;lt;/code&amp;gt; for successful connections only.'''&lt;br /&gt;
*{{SourceMod API|file=clients|function=OnClientAuthorized}} - Called when a player gets a Steam ID.  It is important to note that this may never be called.  It may occur any time in between &amp;lt;code&amp;gt;OnClientConnected&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;OnClientPreAdminCheck&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;OnClientDisconnect&amp;lt;/code&amp;gt;.  Do not rely on it unless you are writing something that needs Steam IDs, and even then you should use &amp;lt;code&amp;gt;OnClientPostAdminCheck&amp;lt;/code&amp;gt;.&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientPutInServer}} - Signifies that the player is fully in-game and {{SourceMod API|file=clients|function=IsClientInGame}} will return true.&lt;br /&gt;
** If you want to check if the player is in-game, you just need to call this; {{SourceMod API|file=clients|function=IsClientConnected}} will also be true if this is (but not the other way around - a player may be connected but not in-game yet).&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientPostAdminCheck}} - Called after the player is '''both authorized and in-game'''.  This is the best callback for checking administrative access after connect.&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientDisconnect}} - Called when a player's disconnection starts.  '''This is paired to &amp;lt;code&amp;gt;OnClientConnected&amp;lt;/code&amp;gt;.'''&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientDisconnect_Post}} - Called when a player's disconnection ends.  '''This is paired to &amp;lt;code&amp;gt;OnClientConnected&amp;lt;/code&amp;gt;.'''&lt;br /&gt;
&lt;br /&gt;
=Frequently Asked Questions=&lt;br /&gt;
==Are plugins reloaded every mapchange?==&lt;br /&gt;
Plugins, by default, are not reloaded on mapchange unless their timestamp changes.  This is a feature so plugin authors have more flexibility with the state of their plugins.  &lt;br /&gt;
&lt;br /&gt;
==Do I need to call CloseHandle in OnPluginEnd?==&lt;br /&gt;
No.  SourceMod automatically closes your Handles when your plugin is unloaded, in order to prevent memory errors.&lt;br /&gt;
&lt;br /&gt;
==Do I need to #include every individual .inc?==&lt;br /&gt;
No.  &amp;lt;tt&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/tt&amp;gt; will give you 95% of the .incs.  Similarly, &amp;lt;tt&amp;gt;#include &amp;lt;sdktools&amp;gt;&amp;lt;/tt&amp;gt; includes everything starting with &amp;lt;sdktools&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Why don't some events fire?==&lt;br /&gt;
There is no guarantee that events will fire.  The event listing is not a specification, it is a list of the events that a game is capable of firing.  Whether the game actually fires them is up to Valve or the developer.&lt;br /&gt;
&lt;br /&gt;
==Do I need to CloseHandle timers?==&lt;br /&gt;
No.  In fact, doing so may cause errors.  Timers naturally die on their own unless they are infinite timers, in which case you can use KillTimer() or die gracefully by returning &amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt; in the callback.&lt;br /&gt;
&lt;br /&gt;
==Are clients disconnected on mapchange?==&lt;br /&gt;
All clients are fully disconnected before the map changes.  They are all reconnected after the next map starts.&lt;br /&gt;
&lt;br /&gt;
If you only want to detect when a client initially connects or leaves your server, hook the [[Generic Source Server Events#player_connect|player_connect]] or [[Generic Source Server Events#player_disconnect|player_disconnect]] events respectively.&lt;br /&gt;
&lt;br /&gt;
==Why am I getting &amp;quot;function prototypes do not match&amp;quot; errors?==&lt;br /&gt;
When you see this error, you'll most likely find that the issue comes from any callback functions referenced in the line(s) that are causing the error.&lt;br /&gt;
&lt;br /&gt;
When you call a function that takes another function as a callback, the callback function must be declared with the correct number of parameter and return types.&lt;br /&gt;
&lt;br /&gt;
For example, [https://sm.alliedmods.net/new-api/console/RegConsoleCmd &amp;lt;tt&amp;gt;RegConsoleCommand&amp;lt;/tt&amp;gt;] must be called with a callback that has with the exact arguments and return type as specified by the [https://sm.alliedmods.net/new-api/console/ConCmd &amp;lt;tt&amp;gt;ConCmd&amp;lt;/tt&amp;gt;] definition.&lt;br /&gt;
&lt;br /&gt;
==When do I need to manually unhook things?==&lt;br /&gt;
You only need to do so when you do not want the callback to fire anymore while the plugin is running.  SourceMod itself, as well as extensions such as SDKHooks, unhooks entities and players when they are removed and disconnected, respectively.  Everything a plugin hooks is unhooked when it is unloaded.&lt;br /&gt;
&lt;br /&gt;
== Why am I seeing references to &amp;lt;tt&amp;gt;STEAM_ID_STOP_IGNORING_RETVALS&amp;lt;/tt&amp;gt;? ==&lt;br /&gt;
When {{SourceMod API|file=clients|function=GetClientAuthId}} is called and returns &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt;, the buffer that should have the client's auth id is populated with &amp;lt;tt&amp;gt;STEAM_ID_STOP_IGNORING_RETVALS&amp;lt;/tt&amp;gt;, both to clear the previous contents of the buffer (thereby preventing accidental reuse of old values) and to inform the developer to stop ignoring the return value of the &amp;lt;code&amp;gt;GetClientAuthId&amp;lt;/code&amp;gt; call.&lt;br /&gt;
&lt;br /&gt;
== Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported? ==&lt;br /&gt;
The engine already exists; Metamod:Source works to some extent.  Further reverse engineering efforts are required to get Metamod:Source in a stable state before work can even start on SourceMod.&lt;br /&gt;
&lt;br /&gt;
No decision has been made yet on if development will be focused on bringing SourceMod to Source 2, on creating a successor scripting ecosystem much like SourceMod was to [[AMX Mod X]], or on extending VScript functionality.&lt;br /&gt;
&lt;br /&gt;
It's safe to say that SourceMod will currently not work on the day of release for any games powered by Source 2.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
For further reading, see the &amp;quot;Scripting&amp;quot; section at the [http://docs.sourcemod.net/ SourceMod Documentation], as well as [https://wiki.alliedmods.net/Scripting_FAQ_(SourceMod) Yak's FAQs on Scripting].&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=Introduction_to_SourceMod_Plugins&amp;diff=11414</id>
		<title>Introduction to SourceMod Plugins</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=Introduction_to_SourceMod_Plugins&amp;diff=11414"/>
		<updated>2023-03-13T15:34:32Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported? */ Bring response up to date; thx duck&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This guide will give you a basic introduction to writing a [[SourceMod]] plugin.  If you are not familiar with the SourcePawn language, it is recommended that you at least briefly read the [[Introduction to SourcePawn]] article.&lt;br /&gt;
&lt;br /&gt;
For information on compiling plugins, see [[Compiling SourceMod Plugins]]. You can use [https://forums.alliedmods.net/showthread.php?p=2693577 SPCode], [https://www.crimsoneditor.com/ Crimson Editor], [http://www.pspad.com/ PSPad], [http://www.ultraedit.com/ UltraEdit], [https://notepad-plus-plus.org/ Notepad++], [https://www.textpad.com/ TextPad], [http://sourceforge.net/projects/pawnstudio/ Pawn Studio], [https://forums.alliedmods.net/showthread.php?t=289127 BasicPawn] or any other text editor you're comfortable with to write plugins.&lt;br /&gt;
&lt;br /&gt;
=Starting from scratch=&lt;br /&gt;
Open your favorite text editor and create a new empty file. When you have an empty file you can just start writing code using the core language, however, you will not be able to use any of SourceMod features because the compiler does not know about them. This is done deliberately so it is possible to use SourcePawn outside of SourceMod. But since we are writing a SourceMod plugin, it is a good idea to enable access to SourceMod features first. This is done using &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; directive. It tells the compiler to &amp;quot;paste&amp;quot; the code from another file into yours.&lt;br /&gt;
&amp;lt;pawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/pawn&amp;gt;&lt;br /&gt;
How does this work? First of all, note that we enclosed file name into angle brackets. Angle brackets tell the compiler to look in the default include directory. By default, it is '''scripting/include'''. You can open it right now and see a lot of inc files there. Those are SourceMod include files that describe various functions, tags and other features available for SourceMod plugins. The files are plain-text and you are encouraged to read them. You will notice, however, that there's not much code in there, certainly not enough to implement all the great features of SourceMod, so where are they? They are implemented inside a SourceMod core which is written in C++ and is compiled into binary files which end up in '''bin''' directory. So how does your SourcePawn code and SM core link together if the compiler doesn't know about the existence of the latter? SourceMod include files are written specially, so they say that the implementation of functions is ''somewhere else''. The compiler understands that and generates a special code that says that this function call is going outside. When SourceMod loads your plugin, it inspects these bits of code and substitutes it's own internal functions instead. This is called [http://en.wikipedia.org/wiki/Dynamic_linking dynamic linking].&lt;br /&gt;
&lt;br /&gt;
=Setting up plugin info=&lt;br /&gt;
Now that we got access to SourceMod features, it is time to set up the information that will be displayed via &amp;lt;tt&amp;gt;sm plugins list&amp;lt;/tt&amp;gt; command. No one likes unnamed plugins. To do that we are going to look inside '''sourcemod.inc''' file and see the format that information should be declared. It's always helpful to look inside SM include files to find out information you don't know. There is also an [http://docs.sourcemod.net/api/ API documentation] but it can be outdated and it only has SM core files so if your plugin is going to use any third party extension or another plugin, you will have to study inc files. So, open '''sourcemod.inc''' and scroll down a bit until you see this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Plugin public information.&lt;br /&gt;
 */&lt;br /&gt;
struct Plugin&lt;br /&gt;
{&lt;br /&gt;
   public const char[] name;		/**&amp;lt; Plugin Name */&lt;br /&gt;
   public const char[] description;	/**&amp;lt; Plugin Description */&lt;br /&gt;
   public const char[] author;		/**&amp;lt; Plugin Author */&lt;br /&gt;
   public const char[] version;		/**&amp;lt; Plugin Version */&lt;br /&gt;
   public const char[] url;			/**&amp;lt; Plugin URL */&lt;br /&gt;
};&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
and this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Declare this as a struct in your plugin to expose its information.&lt;br /&gt;
 * Example:&lt;br /&gt;
 *&lt;br /&gt;
 * public Plugin myinfo =&lt;br /&gt;
 * {&lt;br /&gt;
 *    name = &amp;quot;My Plugin&amp;quot;,&lt;br /&gt;
 *    //etc&lt;br /&gt;
 * };&lt;br /&gt;
 */&lt;br /&gt;
public Plugin myinfo;&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It tells us that we need to create a global public variable &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; which must be of type &amp;lt;tt&amp;gt;Plugin&amp;lt;/tt&amp;gt; which is a struct with 5 fields which themselves are strings. It may sound complicated for a beginner but it's easy. Let's go ahead and create one:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt; keyword means that SourceMod will be able to directly access our variable. &amp;lt;tt&amp;gt;Plugin&amp;lt;/tt&amp;gt; defines a type of our variable. &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; is, obviously, a name of our variable as required by SourceMod. You see that we initialize it right away. This is the preferable way to fill out plugin info.&lt;br /&gt;
&lt;br /&gt;
After that the full code of your plugin should look like this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Getting code to run=&lt;br /&gt;
We already include SourceMod features and filled up or plugin info. We now have a perfectly well-formed plugin which can be compiled and loaded by SourceMod. However, there is one problem - it does nothing. You might be tempted to just start writing a code after &amp;lt;tt&amp;gt;myinfo&amp;lt;/tt&amp;gt; declaration just to see that it will not compile. SourcePawn, unlike other scripting languages like Lua, does not allow a code to be outside of functions. After reading that, you may probably want to just define some function, name it &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; probably, compile and load a plugin and see that your code never gets called. So how do we make SourceMod call our code? For this exact reason, we have forwards. Forwards are function prototypes declared by one party that can be implemented by another party as a [http://en.wikipedia.org/wiki/Callback_%28computer_programming%29 callback]. When a first party starts a forward call, all parties that have matching callbacks receive the call. SourceMod declares a plenty of interesting forwards that we can implement. As you can see, forwards are the only way to get our code executed, keep that in mind. So let's implement &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt; forward. As you may have guessed, it is called when our plugin starts. To do that, we'll have to look up the declaration of &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt;. It is declared inside '''sourcemod.inc''', a file we are already familiar with, let's find it:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Called when the plugin is fully initialized and all known external references &lt;br /&gt;
 * are resolved. This is only called once in the lifetime of the plugin, and is &lt;br /&gt;
 * paired with OnPluginEnd().&lt;br /&gt;
 *&lt;br /&gt;
 * If any run-time error is thrown during this callback, the plugin will be marked &lt;br /&gt;
 * as failed.&lt;br /&gt;
 *&lt;br /&gt;
 * It is not necessary to close any handles or remove hooks in this function.  &lt;br /&gt;
 * SourceMod guarantees that plugin shutdown automatically and correctly releases &lt;br /&gt;
 * all resources.&lt;br /&gt;
 *&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
forward void OnPluginStart();&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
Empty parentheses tell us that no arguments are passed inside this forward, &amp;lt;tt&amp;gt;@noreturn&amp;lt;/tt&amp;gt; inside documentation tells us that we don't have to return anything, pretty simple forward. So how to write a correct callback for it? Firstly, our callback must have the same name, so it's &amp;lt;tt&amp;gt;OnPluginStart&amp;lt;/tt&amp;gt;, secondly, our callback should have the same number of arguments, none in this case, and lastly, SourceMod needs to be able to call our callback so it needs to be &amp;lt;tt&amp;gt;public&amp;lt;/tt&amp;gt;. So the implementation looks like this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we can write code inside curly braces and it will be executed when our plugin starts. Let's output &amp;lt;tt&amp;gt;&amp;quot;Hello world!&amp;quot;&amp;lt;/tt&amp;gt; to server console. To do that we are going to use &amp;lt;tt&amp;gt;PrintToServer&amp;lt;/tt&amp;gt; function. It is declared inside '''console.inc''', however, we don't need to manually include '''console.inc''' because it is included automatically as part of '''sourcemod.inc'''.&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;/**&lt;br /&gt;
 * Sends a message to the server console.&lt;br /&gt;
 *&lt;br /&gt;
 * @param format		Formatting rules.&lt;br /&gt;
 * @param ...			Variable number of format parameters.&lt;br /&gt;
 * @noreturn&lt;br /&gt;
 */&lt;br /&gt;
native int PrintToServer(const char[] format, any ...);&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
As you can see, this is a native function. It is implemented inside SM core. Judging by it's arguments, we can see that it is a [[Format_Class_Functions_%28SourceMod_Scripting%29|format class function]]. However, we don't need any formatting right now, so let's just pass &amp;lt;tt&amp;gt;&amp;quot;Hello world!&amp;quot;&amp;lt;/tt&amp;gt; string as an only argument:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Hello world!&amp;quot;);&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
That's it! The full code of your plugin should look like this:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	PrintToServer(&amp;quot;Hello world!&amp;quot;);&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
Compile and load your plugin on your server and see for yourself that the message is displayed in the server console.&lt;br /&gt;
&lt;br /&gt;
=Includes=&lt;br /&gt;
Pawn requires '''include files''', much like C requires header files.  Include files list all of the structures, functions, callbacks, and tags that are available.  There are three types of include files:&lt;br /&gt;
*'''Core''' - &amp;lt;tt&amp;gt;sourcemod.inc&amp;lt;/tt&amp;gt; and anything it includes.  These are all provided by SourceMod's Core.&lt;br /&gt;
*'''Extension''' - adds a dependency against a certain extension.&lt;br /&gt;
*'''Plugin''' - adds a dependency against a certain plugin.&lt;br /&gt;
&lt;br /&gt;
Include files are loaded using the &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; compiler directive.&lt;br /&gt;
&lt;br /&gt;
=Commands=&lt;br /&gt;
Our first example will be writing a simple admin command to slap a player.  We'll continue to extend this example with more features until we have a final, complete result.&lt;br /&gt;
&lt;br /&gt;
==Declaration==&lt;br /&gt;
First, let's look at what an admin command requires.  Admin commands are registered using the [https://sm.alliedmods.net/new-api/console/RegAdminCmd RegAdminCmd] function.  They require a '''name''', a '''callback function''', and '''default admin flags'''.  &lt;br /&gt;
&lt;br /&gt;
The callback function is what's invoked every time the command is used.  [https://sm.alliedmods.net/new-api/console/ConCmd Click here] to see its prototype.  Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now we've successfully implemented a command -- though it doesn't do anything yet.  In fact, it will say &amp;quot;Unknown command&amp;quot; if you use it! This is because you're not returning Plugin_Handled in your callback. Since you haven't,  SourceMod believes you didn't want the Source Engine to know the command was registered, and it handles it so. The reason SourceMod expects your function to return Plugin_Handled is because of the Action tag you put in your function's prototype. The Action tag specifies that Command_MySlap must return one of four things. See the [https://sm.alliedmods.net/new-api/core/Action Action] enumeration in the sourcemod API to learn more about these return types and when to use them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now the command will report no error, but it still won't do anything. This is because returning &amp;quot;Plugin_Handled&amp;quot; in a command callback will prevent the engine from processing the command. The engine will never even see that the command was run. This is what you will want to do if you are registering a completely new command through SourceMod.&lt;br /&gt;
&lt;br /&gt;
==Implementation==&lt;br /&gt;
Let's decide what the command will look like.  Let's have it act like the default &amp;lt;tt&amp;gt;sm_slap&amp;lt;/tt&amp;gt; command:&lt;br /&gt;
&amp;lt;pre&amp;gt;sm_myslap &amp;lt;name|#userid&amp;gt; [damage]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To implement this, we'll need a few steps:&lt;br /&gt;
*Get the input from the console.  For this we use [https://sm.alliedmods.net/new-api/console/GetCmdArg GetCmdArg()].&lt;br /&gt;
*Find a matching player.  For this we use [https://sm.alliedmods.net/new-api/helpers/FindTarget FindTarget()].&lt;br /&gt;
*Slap them.  For this we use [https://sm.alliedmods.net/new-api/sdktools_functions/SlapPlayer SlapPlayer()], which requires including &amp;lt;tt&amp;gt;sdktools&amp;lt;/tt&amp;gt;, an extension bundled with SourceMod.&lt;br /&gt;
*Respond to the admin.  For this we use [https://sm.alliedmods.net/new-api/console/ReplyToCommand ReplyToCommand()].&lt;br /&gt;
&lt;br /&gt;
Full example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
#include &amp;lt;sdktools&amp;gt;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0.0.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
	LoadTranslations(&amp;quot;common.phrases.txt&amp;quot;); // Required for FindTarget fail reply&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	&lt;br /&gt;
	/* By default, we set damage = 0 */&lt;br /&gt;
	int damage = 0;&lt;br /&gt;
&lt;br /&gt;
	/* Get the first argument */&lt;br /&gt;
	GetCmdArg(1, arg1, sizeof(arg1));&lt;br /&gt;
&lt;br /&gt;
	/* If there are 2 or more arguments, we set damage to&lt;br /&gt;
	 * what the user specified. If a damage isn't specified&lt;br /&gt;
	 * then it will stay zero. */&lt;br /&gt;
	if (args &amp;gt;= 2)&lt;br /&gt;
	{&lt;br /&gt;
		GetCmdArg(2, arg2, sizeof(arg2));&lt;br /&gt;
		damage = StringToInt(arg2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/* Try and find a matching player */&lt;br /&gt;
	int target = FindTarget(client, arg1);&lt;br /&gt;
	if (target == -1)&lt;br /&gt;
	{&lt;br /&gt;
		/* FindTarget() automatically replies with the &lt;br /&gt;
		 * failure reason and returns -1 so we know not &lt;br /&gt;
		 * to continue&lt;br /&gt;
		 */&lt;br /&gt;
		return Plugin_Handled;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	SlapPlayer(target, damage);&lt;br /&gt;
	ReplyToCommand(client, &amp;quot;[SM] You slapped %N for %d damage!&amp;quot;, target, damage);&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information on what %N and %d are, see [[Format Class Functions (SourceMod Scripting)|Format Class Functions]].  Note that you never need to unregister or remove your admin command.  When a plugin is unloaded, SourceMod cleans it up for you.&lt;br /&gt;
&lt;br /&gt;
=ConVars=&lt;br /&gt;
ConVars, also known as cvars, are global console variables in the Source engine.  They can have integer, float, or string values.  ConVar accessing is done through [[Handles (SourceMod Scripting)|Handles]].  Since ConVars are global, you do not need to close ConVar Handles (in fact, you cannot).&lt;br /&gt;
&lt;br /&gt;
The handy feature of ConVars is that they are easy for users to configure.  They can be placed in any .cfg file, such as &amp;lt;tt&amp;gt;server.cfg&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;sourcemod.cfg&amp;lt;/tt&amp;gt;.  To make this easier, SourceMod has an [https://sm.alliedmods.net/new-api/sourcemod/AutoExecConfig AutoExecConfig()] function.  This function will automatically build a default .cfg file containing all of your cvars, annotated with comments, for users.  It is highly recommended that you call this if you have customizable ConVars.&lt;br /&gt;
&lt;br /&gt;
Let's extend your example from earlier with a new ConVar.  Our ConVar will be &amp;lt;tt&amp;gt;g_cvarMySlapDamage&amp;lt;/tt&amp;gt; and will specify the default damage someone is slapped for if no damage is specified.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;ConVar g_cvarMySlapDamage = null;&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
&lt;br /&gt;
	g_cvarMySlapDamage = CreateConVar(&amp;quot;sm_myslap_damage&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;Default slap damage&amp;quot;);&lt;br /&gt;
	AutoExecConfig(true, &amp;quot;plugin_myslap&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage = g_cvarMySlapDamage.IntValue;&lt;br /&gt;
&lt;br /&gt;
	/* The rest remains unchanged! */&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Showing Activity, Logging=&lt;br /&gt;
Almost all admin commands should log their activity, and some admin commands should show their activity to in-game clients.  This can be done via the [https://sm.alliedmods.net/new-api/logging/LogAction LogAction()] and [https://sm.alliedmods.net/new-api/console/ShowActivity2 ShowActivity2()] functions.  The exact functionality of ShowActivity2() is determined by the &amp;lt;tt&amp;gt;sm_show_activity&amp;lt;/tt&amp;gt; cvar.&lt;br /&gt;
&lt;br /&gt;
For example, let's rewrite the last few lines of our slap command:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
	SlapPlayer(target, damage);&lt;br /&gt;
&lt;br /&gt;
	char name[MAX_NAME_LENGTH];&lt;br /&gt;
	&lt;br /&gt;
	GetClientName(target, name, sizeof(name));&lt;br /&gt;
&lt;br /&gt;
	ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %s for %d damage!&amp;quot;, name, damage);&lt;br /&gt;
	LogAction(client, target, &amp;quot;\&amp;quot;%L\&amp;quot; slapped \&amp;quot;%L\&amp;quot; (damage %d)&amp;quot;, client, target, damage);&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Multiple Targets=&lt;br /&gt;
To fully complete our slap demonstration, let's make it support multiple targets.  SourceMod's [[Admin_Commands_%28SourceMod%29#How_to_Target|targeting system]] is quite advanced, so using it may seem complicated at first.  &lt;br /&gt;
&lt;br /&gt;
The function we use is [https://sm.alliedmods.net/new-api/commandfilters/ProcessTargetString ProcessTargetString()].  It takes in input from the console and returns a list of matching clients.  It also returns a noun that will identify either a single client or describe a list of clients.  The idea is that each client is then processed, but the activity shown to all players is only processed once.  This reduces screen spam.&lt;br /&gt;
&lt;br /&gt;
This method of target processing is used for almost every admin command in SourceMod, and in fact, FindTarget() is just a simplified version.&lt;br /&gt;
&lt;br /&gt;
Full, final example:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
#include &amp;lt;sourcemod&amp;gt;&lt;br /&gt;
#include &amp;lt;sdktools&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ConVar g_cvarMySlapDamage = null;&lt;br /&gt;
&lt;br /&gt;
public Plugin myinfo =&lt;br /&gt;
{&lt;br /&gt;
	name = &amp;quot;My First Plugin&amp;quot;,&lt;br /&gt;
	author = &amp;quot;Me&amp;quot;,&lt;br /&gt;
	description = &amp;quot;My first plugin ever&amp;quot;,&lt;br /&gt;
	version = &amp;quot;1.0.0.0&amp;quot;,&lt;br /&gt;
	url = &amp;quot;http://www.sourcemod.net/&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
	RegAdminCmd(&amp;quot;sm_myslap&amp;quot;, Command_MySlap, ADMFLAG_SLAY);&lt;br /&gt;
	LoadTranslations(&amp;quot;common.phrases.txt&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	g_cvarMySlapDamage = CreateConVar(&amp;quot;sm_myslap_damage&amp;quot;, &amp;quot;5&amp;quot;, &amp;quot;Default slap damage&amp;quot;);&lt;br /&gt;
	AutoExecConfig(true, &amp;quot;plugin_myslap&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public Action Command_MySlap(int client, int args)&lt;br /&gt;
{&lt;br /&gt;
	char arg1[32], arg2[32];&lt;br /&gt;
	int damage = g_cvarMySlapDamage.IntValue;&lt;br /&gt;
&lt;br /&gt;
	/* Get the first argument */&lt;br /&gt;
	GetCmdArg(1, arg1, sizeof(arg1));&lt;br /&gt;
&lt;br /&gt;
	/* If there are 2 or more arguments, and the second argument fetch &lt;br /&gt;
	 * is successful, convert it to an integer.&lt;br /&gt;
	 */&lt;br /&gt;
	if (args &amp;gt;= 2 &amp;amp;&amp;amp; GetCmdArg(2, arg2, sizeof(arg2)))&lt;br /&gt;
	{&lt;br /&gt;
		damage = StringToInt(arg2);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	/**&lt;br /&gt;
	 * target_name - stores the noun identifying the target(s)&lt;br /&gt;
	 * target_list - array to store clients&lt;br /&gt;
	 * target_count - variable to store number of clients&lt;br /&gt;
	 * tn_is_ml - stores whether the noun must be translated&lt;br /&gt;
	 */&lt;br /&gt;
	char target_name[MAX_TARGET_LENGTH];&lt;br /&gt;
	int target_list[MAXPLAYERS], target_count;&lt;br /&gt;
	bool tn_is_ml;&lt;br /&gt;
&lt;br /&gt;
	if ((target_count = ProcessTargetString(&lt;br /&gt;
			arg1,&lt;br /&gt;
			client,&lt;br /&gt;
			target_list,&lt;br /&gt;
			MAXPLAYERS,&lt;br /&gt;
			COMMAND_FILTER_ALIVE, /* Only allow alive players */&lt;br /&gt;
			target_name,&lt;br /&gt;
			sizeof(target_name),&lt;br /&gt;
			tn_is_ml)) &amp;lt;= 0)&lt;br /&gt;
	{&lt;br /&gt;
		/* This function replies to the admin with a failure message */&lt;br /&gt;
		ReplyToTargetError(client, target_count);&lt;br /&gt;
		return Plugin_Handled;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (int i = 0; i &amp;lt; target_count; i++)&lt;br /&gt;
	{&lt;br /&gt;
		SlapPlayer(target_list[i], damage);&lt;br /&gt;
		LogAction(client, target_list[i], &amp;quot;\&amp;quot;%L\&amp;quot; slapped \&amp;quot;%L\&amp;quot; (damage %d)&amp;quot;, client, target_list[i], damage);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (tn_is_ml)&lt;br /&gt;
	{&lt;br /&gt;
		ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %t for %d damage!&amp;quot;, target_name, damage);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		ShowActivity2(client, &amp;quot;[SM] &amp;quot;, &amp;quot;Slapped %s for %d damage!&amp;quot;, target_name, damage);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return Plugin_Handled;&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Events=&lt;br /&gt;
Events are informational notification messages passed between objects in the server.  Many are also passed from the server to the client.  They are defined in .res files under the &amp;lt;tt&amp;gt;hl2/resource&amp;lt;/tt&amp;gt; folder and &amp;lt;tt&amp;gt;resource&amp;lt;/tt&amp;gt; folders of specific mods.  For a basic listing, see [[Game Events (Source)|Source Game Events]].&lt;br /&gt;
&lt;br /&gt;
It is important to note a few concepts about events:&lt;br /&gt;
*They are almost always informational.  That is, blocking &amp;lt;tt&amp;gt;player_death&amp;lt;/tt&amp;gt; will not stop a player from dying.  It may block a HUD or console message or something else minor.&lt;br /&gt;
*They almost always use userids instead of client indexes.&lt;br /&gt;
*Just because it is in a resource file does not mean it is ever called, or works the way you expect it to.  Mods are notorious for not properly documenting their event functionality.&lt;br /&gt;
&lt;br /&gt;
An example of finding when a player dies:&lt;br /&gt;
&amp;lt;sourcepawn&amp;gt;&lt;br /&gt;
public void OnPluginStart()&lt;br /&gt;
{&lt;br /&gt;
   HookEvent(&amp;quot;player_death&amp;quot;, Event_PlayerDeath);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
public void Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)&lt;br /&gt;
{&lt;br /&gt;
   int victim_id = event.GetInt(&amp;quot;userid&amp;quot;);&lt;br /&gt;
   int attacker_id = event.GetInt(&amp;quot;attacker&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
   int victim = GetClientOfUserId(victim_id);&lt;br /&gt;
   int attacker = GetClientOfUserId(attacker_id);&lt;br /&gt;
&lt;br /&gt;
   /* CODE */&lt;br /&gt;
}&amp;lt;/sourcepawn&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Callback Orders and Pairing=&lt;br /&gt;
SourceMod has a number of builtin callbacks about the state of the server and plugin.  Some of these are paired in special ways which can confuse users.&lt;br /&gt;
&lt;br /&gt;
==Pairing==&lt;br /&gt;
'''Pairing''' is SourceMod terminology.  Examples of it are:&lt;br /&gt;
*OnMapEnd() cannot be called without an OnMapStart(), and if OnMapStart() is called, it cannot be called again without an OnMapEnd().&lt;br /&gt;
*OnClientConnected(N) for a given client N will only be called once until an OnClientDisconnected(N) for the same client N is called (which is guaranteed to happen).&lt;br /&gt;
&lt;br /&gt;
There is a formal definition of SourceMod's pairing.  For two functions X and Y, both with input A, the following conditions hold:&lt;br /&gt;
*If X is invoked with input A, it cannot be invoked again with the same input unless Y is called with input A.&lt;br /&gt;
*If X is invoked with input A, it is guaranteed that Y will, at some point, be called with input A.&lt;br /&gt;
*Y cannot be invoked with any input A unless X was called first with input A.&lt;br /&gt;
*The relationship is described as, &amp;quot;X is paired with Y,&amp;quot; and &amp;quot;Y is paired to X.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==General Callbacks==&lt;br /&gt;
These callbacks are listed in the order they are called, in the lifetime of a plugin and the server.&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=AskPluginLoad2}} - Called once, immediately after the plugin is loaded from the disk.  This function can be used to stop a plugin from loading and return a custom error message; return APLRes_Failure and use strcopy on to replace the error string.  All CreateNative and RegPluginLibrary calls should be done here.  &lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnPluginStart}} - Called once, after the plugin has been fully initialized and can proceed to load.  Any run-time errors in this function will cause the plugin to fail to load.  '''This is paired with OnPluginEnd()'''.&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnAllPluginsLoaded}} - Called once, after all non-late loaded plugins have called OnPluginStart.  &lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnMapStart}} - Called every time the map loads.  If the plugin is loaded late, and the map has already started, this function is called anyway after load, in order to preserve pairing.  '''This function is paired with OnMapEnd().'''&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnConfigsExecuted}} - Called once per map-change after &amp;lt;tt&amp;gt;servercfgfile&amp;lt;/tt&amp;gt; (usually &amp;lt;tt&amp;gt;server.cfg&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;sourcemod.cfg&amp;lt;/tt&amp;gt;, and all plugin config files have finished executing.  If a plugin is loaded after this has happened, the callback is called anyway, in order to preserve pairing.  '''This function is paired with OnMapEnd().'''&lt;br /&gt;
*At this point, most game callbacks can occur, such as events and callbacks involving clients (or other things, like OnGameFrame).&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnMapEnd}} - Called when the map is about to end.  At this point, all clients are disconnected, but &amp;lt;tt&amp;gt;TIMER_NO_MAPCHANGE&amp;lt;/tt&amp;gt; timers are not yet destroyed.  '''This function is paired to OnMapStart().'''&lt;br /&gt;
* {{SourceMod API|file=sourcemod|function=OnPluginEnd}} - Called once, immediately before the plugin is unloaded.  '''This function is paired to OnPluginStart().'''&lt;br /&gt;
&lt;br /&gt;
==Client Callbacks==&lt;br /&gt;
These callbacks are listed in no specific order, however, their documentation holds for both fake and real clients.&lt;br /&gt;
&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientConnect}} - Called when a player initiates a connection.  You can block a player from connecting by returning &amp;lt;code&amp;gt;Plugin_Stop&amp;lt;/code&amp;gt; and setting rejectmsg to an error message.&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientConnected}} - Called after a player connects. Signifies that the player is connected and {{SourceMod API|file=clients|function=IsClientConnected}} will return true. '''This is paired with &amp;lt;code&amp;gt;OnClientDisconnect&amp;lt;/code&amp;gt; for successful connections only.'''&lt;br /&gt;
*{{SourceMod API|file=clients|function=OnClientAuthorized}} - Called when a player gets a Steam ID.  It is important to note that this may never be called.  It may occur any time in between &amp;lt;code&amp;gt;OnClientConnected&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;OnClientPreAdminCheck&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;OnClientDisconnect&amp;lt;/code&amp;gt;.  Do not rely on it unless you are writing something that needs Steam IDs, and even then you should use &amp;lt;code&amp;gt;OnClientPostAdminCheck&amp;lt;/code&amp;gt;.&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientPutInServer}} - Signifies that the player is fully in-game and {{SourceMod API|file=clients|function=IsClientInGame}} will return true.&lt;br /&gt;
** If you want to check if the player is in-game, you just need to call this; {{SourceMod API|file=clients|function=IsClientConnected}} will also be true if this is (but not the other way around - a player may be connected but not in-game yet).&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientPostAdminCheck}} - Called after the player is '''both authorized and in-game'''.  This is the best callback for checking administrative access after connect.&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientDisconnect}} - Called when a player's disconnection starts.  '''This is paired to &amp;lt;code&amp;gt;OnClientConnected&amp;lt;/code&amp;gt;.'''&lt;br /&gt;
* {{SourceMod API|file=clients|function=OnClientDisconnect_Post}} - Called when a player's disconnection ends.  '''This is paired to &amp;lt;code&amp;gt;OnClientConnected&amp;lt;/code&amp;gt;.'''&lt;br /&gt;
&lt;br /&gt;
=Frequently Asked Questions=&lt;br /&gt;
==Are plugins reloaded every mapchange?==&lt;br /&gt;
Plugins, by default, are not reloaded on mapchange unless their timestamp changes.  This is a feature so plugin authors have more flexibility with the state of their plugins.  &lt;br /&gt;
&lt;br /&gt;
==Do I need to call CloseHandle in OnPluginEnd?==&lt;br /&gt;
No.  SourceMod automatically closes your Handles when your plugin is unloaded, in order to prevent memory errors.&lt;br /&gt;
&lt;br /&gt;
==Do I need to #include every individual .inc?==&lt;br /&gt;
No.  &amp;lt;tt&amp;gt;#include &amp;lt;sourcemod&amp;gt;&amp;lt;/tt&amp;gt; will give you 95% of the .incs.  Similarly, &amp;lt;tt&amp;gt;#include &amp;lt;sdktools&amp;gt;&amp;lt;/tt&amp;gt; includes everything starting with &amp;lt;sdktools&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Why don't some events fire?==&lt;br /&gt;
There is no guarantee that events will fire.  The event listing is not a specification, it is a list of the events that a game is capable of firing.  Whether the game actually fires them is up to Valve or the developer.&lt;br /&gt;
&lt;br /&gt;
==Do I need to CloseHandle timers?==&lt;br /&gt;
No.  In fact, doing so may cause errors.  Timers naturally die on their own unless they are infinite timers, in which case you can use KillTimer() or die gracefully by returning &amp;lt;tt&amp;gt;Plugin_Stop&amp;lt;/tt&amp;gt; in the callback.&lt;br /&gt;
&lt;br /&gt;
==Are clients disconnected on mapchange?==&lt;br /&gt;
All clients are fully disconnected before the map changes.  They are all reconnected after the next map starts.&lt;br /&gt;
&lt;br /&gt;
If you only want to detect when a client initially connects or leaves your server, hook the [[Generic Source Server Events#player_connect|player_connect]] or [[Generic Source Server Events#player_disconnect|player_disconnect]] events respectively.&lt;br /&gt;
&lt;br /&gt;
==Why am I getting &amp;quot;function prototypes do not match&amp;quot; errors?==&lt;br /&gt;
When you see this error, you'll most likely find that the issue comes from any callback functions referenced in the line(s) that are causing the error.&lt;br /&gt;
&lt;br /&gt;
When you call a function that takes another function as a callback, the callback function must be declared with the correct number of parameter and return types.&lt;br /&gt;
&lt;br /&gt;
For example, [https://sm.alliedmods.net/new-api/console/RegConsoleCmd &amp;lt;tt&amp;gt;RegConsoleCommand&amp;lt;/tt&amp;gt;] must be called with a callback that has with the exact arguments and return type as specified by the [https://sm.alliedmods.net/new-api/console/ConCmd &amp;lt;tt&amp;gt;ConCmd&amp;lt;/tt&amp;gt;] definition.&lt;br /&gt;
&lt;br /&gt;
==When do I need to manually unhook things?==&lt;br /&gt;
You only need to do so when you do not want the callback to fire anymore while the plugin is running.  SourceMod itself, as well as extensions such as SDKHooks, unhooks entities and players when they are removed and disconnected, respectively.  Everything a plugin hooks is unhooked when it is unloaded.&lt;br /&gt;
&lt;br /&gt;
== Why am I seeing references to &amp;lt;tt&amp;gt;STEAM_ID_STOP_IGNORING_RETVALS&amp;lt;/tt&amp;gt;? ==&lt;br /&gt;
When {{SourceMod API|file=clients|function=GetClientAuthId}} is called and returns &amp;lt;tt&amp;gt;false&amp;lt;/tt&amp;gt;, the buffer that should have the client's auth id is populated with &amp;lt;tt&amp;gt;STEAM_ID_STOP_IGNORING_RETVALS&amp;lt;/tt&amp;gt;, both to clear the previous contents of the buffer (thereby preventing accidental reuse of old values) and to inform the developer to stop ignoring the return value of the &amp;lt;code&amp;gt;GetClientAuthId&amp;lt;/code&amp;gt; call.&lt;br /&gt;
&lt;br /&gt;
== Will SourceMod support Source 2? Will plugins for existing games continue to work if they are ported? ==&lt;br /&gt;
The engine already exists; Metamod:Source works to some extent.  Further reverse engineering efforts are required to get Metamod:Source in a stable state before work can even start on SourceMod.&lt;br /&gt;
&lt;br /&gt;
No decision has been made yet on if development will be focused on bringing SourceMod to Source 2, on creating a successor scripting ecosystem much like SourceMod was to [[AMX Mod X]], or on extending VScript functionality.&lt;br /&gt;
&lt;br /&gt;
It's likely safe to say that SourceMod will not work on day 1 of the release of Source 2.&lt;br /&gt;
&lt;br /&gt;
=Further Reading=&lt;br /&gt;
For further reading, see the &amp;quot;Scripting&amp;quot; section at the [http://docs.sourcemod.net/ SourceMod Documentation], as well as [https://wiki.alliedmods.net/Scripting_FAQ_(SourceMod) Yak's FAQs on Scripting].&lt;br /&gt;
&lt;br /&gt;
[[Category:SourceMod Scripting]]&lt;br /&gt;
&lt;br /&gt;
{{LanguageSwitch}}&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/How_to_X&amp;diff=11413</id>
		<title>User:Nosoop/Guide/How to X</title>
		<link rel="alternate" type="text/html" href="https://wiki.alliedmods.net/index.php?title=User:Nosoop/Guide/How_to_X&amp;diff=11413"/>
		<updated>2023-03-04T16:53:27Z</updated>

		<summary type="html">&lt;p&gt;Nosoop: /* Proper Unicode handling in MySQL */ Add note on converting existing data&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is a page on how to do things that are common in plugins.&lt;br /&gt;
These are intended to be best practices.&lt;br /&gt;
&lt;br /&gt;
= Determine if a client has access to something =&lt;br /&gt;
&lt;br /&gt;
Use the admin overrides system with the {{SourceMod API|file=console|function=CheckCommandAccess}} function.&lt;br /&gt;
For example, if you want to determine if a client has access to the &amp;lt;code&amp;gt;sm_ban&amp;lt;/code&amp;gt; command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;&lt;br /&gt;
if (CheckCommandAccess(client, &amp;quot;sm_ban&amp;quot;, ADMFLAG_BAN)) {&lt;br /&gt;
    // client has access to the &amp;quot;sm_ban&amp;quot; command&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;command&amp;lt;/code&amp;gt; parameter can be an arbitrary string; it does not have to point to a valid command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;sourcepawn&amp;quot;&amp;gt;&lt;br /&gt;
if (CheckCommandAccess(client, &amp;quot;has_fancy_color_trails&amp;quot;, ADMFLAG_CUSTOM1, true)) {&lt;br /&gt;
    // client has access to the &amp;quot;has_fancy_color_trails&amp;quot; override;&lt;br /&gt;
    // if an override entry isn't set it falls back to ADMFLAG_CUSTOM1.&lt;br /&gt;
    // ignores the privileges set on a command of that name if it exists&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Under no circumstance should you leave the &amp;lt;code&amp;gt;command&amp;lt;/code&amp;gt; parameter blank; even if you want to check access based on existing admin flags, you should provide a unique &amp;quot;command&amp;quot; string to allow server operators to override access themselves.&lt;br /&gt;
&lt;br /&gt;
To assign access levels for specific strings, modify &amp;lt;tt&amp;gt;configs/admin_overrides.cfg&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For more detailed information, see [[Overriding_Command_Access_(SourceMod)|this page on overriding command access]].&lt;br /&gt;
&lt;br /&gt;
= Declare methodmap natives =&lt;br /&gt;
&lt;br /&gt;
Methodmap natives are the same as any other native, except that the &amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt; value is passed in as the first parameter, and any additional parameters follow it.&lt;br /&gt;
&lt;br /&gt;
= Pass enum structs through natives =&lt;br /&gt;
&lt;br /&gt;
In short, you don't.  Enum structs do not (at the time of writing) have a standardized in-memory representation, so they should not be passed across plugin boundaries.  There's also no way to guarantee that two plugins were compiled with the same definition, let alone implementation (though checking the offset / sizes of each member would lower the risk).&lt;br /&gt;
&lt;br /&gt;
The safest approach is to serialize / deserialize the data through a standard container ({{SourceMod API|file=adt_trie|function=StringMap}}, {{SourceMod API|file=datapack|function=DataPack}}).  That is then exposed to other plugins as an [https://en.wikipedia.org/wiki/Opaque_pointer opaque handle] (the methodmap definition would inherit from &amp;lt;tt&amp;gt;Handle&amp;lt;/tt&amp;gt;, and read / write operations are handled indirectly through natives registered by the originating plugin).&lt;br /&gt;
&lt;br /&gt;
= Add linebreaks in CS:GO chat messages =&lt;br /&gt;
&lt;br /&gt;
CS:GO uses the newline character &amp;lt;code&amp;gt;\n&amp;lt;/code&amp;gt; as a text color.  Use the paragraph separator character instead: &amp;lt;code&amp;gt;\xE2\x80\xA9&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Proper Unicode handling in MySQL =&lt;br /&gt;
&lt;br /&gt;
MySQL defaults to using the &amp;lt;tt&amp;gt;latin1&amp;lt;/tt&amp;gt; character encoding, which isn't good if you need to store non-ASCII text.&lt;br /&gt;
&lt;br /&gt;
* Ensure columns are created with the &amp;lt;tt&amp;gt;utf8mb4&amp;lt;/tt&amp;gt; collation, ''not'' &amp;lt;tt&amp;gt;utf8&amp;lt;/tt&amp;gt; (which aliases to &amp;lt;tt&amp;gt;utf8mb3&amp;lt;/tt&amp;gt;).&lt;br /&gt;
* After connecting to the database, call {{SourceMod API|file=dbi|class=Database|function=SetCharset}} with &amp;lt;tt&amp;gt;utf8&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If you have previous entries that were encoded as &amp;lt;tt&amp;gt;latin1&amp;lt;/tt&amp;gt;, refer to [https://stackoverflow.com/a/9407998 this StackOverflow answer] to convert it.  Do note that the outermost &amp;lt;code&amp;gt;convert&amp;lt;/code&amp;gt; operation should use &amp;lt;tt&amp;gt;utf8mb4&amp;lt;/tt&amp;gt; instead.&lt;/div&gt;</summary>
		<author><name>Nosoop</name></author>
		
	</entry>
</feed>