Paths
Where Source2Mod keeps configs, gamedata, plugins and shared data — ask instead of hard-coding paths.
ISource2ModPaths tells a plugin where things are on disk. Ask it rather than
spelling paths out against the game directory: when the layout moves, every
plugin that asks keeps working without an edit.
#include "source2mod/ISource2ModPaths.h"#include <source2mod/api> // the whole API, paths.inc includedThe layout
Under the game directory (.../game/csgo):
addons/source2mod/
configs/ core.json, and one directory per plugin
<PluginName>/ this plugin's own configs
gamedata/ every .json here is read into the game config
plugins/ the .smx files themselves
shared/ data more than one plugin reads| Call | Macro | Path |
|---|---|---|
GameDirectory() | SOURCE2MOD_GAME_DIR() | The game directory, e.g. .../game/csgo |
RootDirectory() | SOURCE2MOD_ROOT_DIR() | addons/source2mod |
ConfigsDirectory() | SOURCE2MOD_CONFIGS_DIR() | addons/source2mod/configs |
GamedataDirectory() | SOURCE2MOD_GAMEDATA_DIR() | addons/source2mod/gamedata |
PluginsDirectory() | SOURCE2MOD_PLUGINS_DIR() | addons/source2mod/plugins |
SharedDirectory() | SOURCE2MOD_SHARED_DIR() | addons/source2mod/shared |
PluginConfigDirectory(PluginId owner) | PLUGIN_CONFIG_DIR() | configs/<PluginName> for this plugin |
All of them are absolute paths built on the game directory, without a trailing
slash — append "/file.json" yourself. In SourcePawn they are
Source2ModPaths.GameDirectory(buffer, maxlen) and so on, writing into a
buffer (char path[PLATFORM_MAX_PATH]); PluginConfigDirectory() there takes
no plugin id, it is always the calling plugin's.
Your plugin's config directory
PLUGIN_CONFIG_DIR() is PluginConfigDirectory(g_PluginID): the
configs/<PluginName> directory, keyed on the name your plugin returns from
GetName(). A script reads the file with Source2ModFiles.ReadFile()
(see Files and KeyValues).
#include <fstream>
#include <sstream>
bool LoadConfig()
{
const char* dir = PLUGIN_CONFIG_DIR();
if (!dir)
return false;
std::ifstream file(std::string(dir) + "/config.json");
if (!file)
return false;
std::stringstream text;
text << file.rdbuf();
ISource2ModJSONDocument* doc = g_pSource2ModJSON->Parse(text.str().c_str());
// ... read values, see the JSON guide ...
doc->Release();
return true;
}bool LoadConfig()
{
char dir[PLATFORM_MAX_PATH], path[PLATFORM_MAX_PATH];
Source2ModPaths.PluginConfigDirectory(dir, sizeof(dir));
if (!dir[0])
return false;
Source2ModApi.Format(path, sizeof(path), "%s/config.json", dir);
char text[4096];
if (Source2ModFiles.ReadFile(path, text, sizeof(text)) < 0)
return false;
ISource2ModJSONDocument doc = Source2ModJSON.Parse(text);
// ... read values, see the JSON guide ...
delete doc;
return true;
}In C++ a small wrapper that turns nullptr into an empty string keeps call
sites simple — FUNPLAY's plugins do this (SourcePawn needs none: it always gets
a string, empty when there is no path):
inline std::string FromSource2Mod(const char* p) { return p ? std::string(p) : std::string(); }
inline std::string ConfigDirectory() { return FromSource2Mod(PLUGIN_CONFIG_DIR()) + "/config"; }Pitfalls
PluginConfigDirectory()can returnnullptr— for an unknownPluginId, or when the plugin'sGetName()is empty. SourcePawn gets an empty string instead.- The directory is not created for you. It is where your plugin's files are expected to have been installed; create it yourself if you write files there.
- Copy the string if you keep it past Source2Mod's lifetime (C++ only; SourcePawn already has its own copy). The returned pointers are owned by Source2Mod and stay valid while it is loaded.
- Ask after load. The game directory is only known once the engine is up;
call these from
Load()/OnPluginStart()or later, not from static initialisers.
Reference
Maps, GeoIP and features
The current and next map, map changes, map history and map lists; where a player or an IP address is from; and checking for optional features before using them.
Game Systems
Register your own IGameSystem with the engine — for precaching in BuildGameSessionManifest and the rest of the game system events.