3 * ===============================================================
4 * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
5 * ===============================================================
7 * This file is not open source and may not be copied without explicit
8 * written permission of AlliedModders LLC. This file may not be redistributed
9 * in whole or significant part.
10 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
15 #include "CoreConfig.h"
16 #include "sourcemod.h"
17 #include "sourcemm_api.h"
18 #include "sm_srvcmds.h"
19 #include "sm_version.h"
20 #include "sm_stringutil.h"
21 #include "LibrarySys.h"
22 #include "TextParsers.h"
24 #include "PluginSys.h"
25 #include "ForwardSys.h"
27 #ifdef PLATFORM_WINDOWS
28 ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
29 #elif defined PLATFORM_LINUX
30 ConVar sm_corecfgfile("sm_corecfgfile", "addons/sourcemod/configs/core.cfg", 0, "SourceMod core configuration file");
33 IForward *g_pOnServerCfg = NULL;
34 IForward *g_pOnConfigsExecuted = NULL;
35 CoreConfig g_CoreConfig;
36 bool g_bConfigsExecd = false;
38 void CoreConfig::OnSourceModAllInitialized()
40 g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this);
41 g_pOnServerCfg = g_Forwards.CreateForward("OnServerCfg", ET_Ignore, 0, NULL);
42 g_pOnConfigsExecuted = g_Forwards.CreateForward("OnConfigsExecuted", ET_Ignore, 0, NULL);
45 void CoreConfig::OnSourceModShutdown()
47 g_RootMenu.RemoveRootConsoleCommand("config", this);
48 g_Forwards.ReleaseForward(g_pOnServerCfg);
49 g_Forwards.ReleaseForward(g_pOnConfigsExecuted);
52 void CoreConfig::OnSourceModLevelChange(const char *mapName)
54 g_bConfigsExecd = false;
57 void CoreConfig::OnRootConsoleCommand(const char *command, unsigned int argcount)
61 const char *option = engine->Cmd_Argv(2);
62 const char *value = engine->Cmd_Argv(3);
66 ConfigResult res = SetConfigOption(option, value, ConfigSource_Console, error, sizeof(error));
68 if (res == ConfigResult_Reject)
70 g_RootMenu.ConsolePrint("[SM] Could not set config option \"%s\" to \"%s\" (%s)", option, value, error);
71 } else if (res == ConfigResult_Ignore) {
72 g_RootMenu.ConsolePrint("[SM] No such config option \"%s\" exists.", option);
74 g_RootMenu.ConsolePrint("Config option \"%s\" successfully set to \"%s.\"", option, value);
80 g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> <value>");
83 void CoreConfig::Initialize()
86 char filePath[PLATFORM_MAX_PATH];
88 /* Try to get command line value of core config convar */
89 const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile");
91 /* If sm_corecfgfile not specified on command line, use default value */
94 corecfg = sm_corecfgfile.GetDefault();
97 /* Format path to config file */
98 g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetGamePath(), corecfg);
100 /* Parse config file */
101 if ((err=g_TextParser.ParseFile_SMC(filePath, this, NULL, NULL)) != SMCParse_Okay)
103 /* :TODO: This won't actually log or print anything :( - So fix that somehow */
104 const char *error = g_TextParser.GetSMCErrorString(err);
105 g_Logger.LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : "");
109 SMCParseResult CoreConfig::ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes)
112 ConfigResult err = SetConfigOption(key, value, ConfigSource_File, error, sizeof(error));
114 if (err == ConfigResult_Reject)
116 /* This is a fatal error */
117 g_Logger.LogFatal("Config error (key: %s) (value: %s) %s", key, value, error);
120 return SMCParse_Continue;
123 ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value, ConfigSource source, char *error, size_t maxlength)
128 SMGlobalClass *pBase = SMGlobalClass::head;
131 if ((result = pBase->OnSourceModConfigChanged(option, value, source, error, maxlength)) != ConfigResult_Ignore)
135 pBase = pBase->m_pGlobalClassNext;
138 return ConfigResult_Ignore;
141 bool SM_AreConfigsExecuted()
143 return g_bConfigsExecd;
146 inline bool IsPathSepChar(char c)
148 #if defined PLATFORM_WINDOWS
149 return (c == '\\' || c == '/');
150 #elif defined PLATFORM_LINUX
155 bool SM_ExecuteConfig(CPlugin *pl, AutoConfig *cfg, bool can_create)
157 bool will_create = false;
159 /* See if we should be creating */
160 if (can_create && cfg->create)
164 /* If the folder does not exist, attempt to create it.
165 * We're awfully nice.
167 const char *folder = cfg->folder.c_str();
168 char path[PLATFORM_MAX_PATH];
169 char build[PLATFORM_MAX_PATH];
171 g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "cfg/%s", folder);
173 if (!g_LibSys.IsPathDirectory(path))
175 char *cur_ptr = path;
178 g_LibSys.PathFormat(path, sizeof(path), "%s", folder);
179 len = g_SourceMod.BuildPath(Path_Game, build, sizeof(build), "cfg");
183 /* Find next suitable path */
184 char *next_ptr = cur_ptr;
185 while (*next_ptr != '\0')
187 if (IsPathSepChar(*next_ptr))
195 if (*next_ptr == '\0')
199 len += g_LibSys.PathFormat(&build[len],
203 if (!g_LibSys.CreateDirectory(build))
212 /* Check if the file exists. */
213 char file[PLATFORM_MAX_PATH];
214 char local[PLATFORM_MAX_PATH];
216 if (cfg->folder.size())
218 g_LibSys.PathFormat(local,
222 cfg->autocfg.c_str());
224 g_LibSys.PathFormat(local,
227 cfg->autocfg.c_str());
230 g_SourceMod.BuildPath(Path_Game, file, sizeof(file), "cfg/%s", local);
232 bool file_exists = g_LibSys.IsPathFile(file);
233 if (!file_exists && will_create)
235 List<const ConVar *> *convars = NULL;
236 if (pl->GetProperty("ConVarList", (void **)&convars, false) && convars)
238 /* Attempt to create it */
239 FILE *fp = fopen(file, "wt");
242 fprintf(fp, "// This file was auto-generated by SourceMod (v%s)\n", SVN_FULL_VERSION);
243 fprintf(fp, "// ConVars for plugin \"%s\"\n", pl->GetFilename());
246 List<const ConVar *>::iterator iter;
248 for (iter = convars->begin(); iter != convars->end(); iter++)
250 const ConVar *cvar = (*iter);
254 /* Print comments until there is no more */
255 strncopy(descr, cvar->GetHelpText(), sizeof(descr));
256 while (*dptr != '\0')
258 /* Find the next line */
259 char *next_ptr = dptr;
260 while (*next_ptr != '\0')
262 if (*next_ptr == '\n')
270 fprintf(fp, "// %s\n", dptr);
274 fprintf(fp, "// -\n");
275 fprintf(fp, "// Default: \"%s\"\n", cvar->GetDefault());
278 fprintf(fp, "// Minimum: \"%02f\"\n", x);
282 fprintf(fp, "// Maximum: \"%02f\"\n", x);
284 fprintf(fp, "%s \"%s\"\n", cvar->GetName(), cvar->GetDefault());
299 UTIL_Format(cmd, sizeof(cmd), "exec %s\n", local);
300 engine->ServerCommand(cmd);
306 void SM_DoSingleExecFwds(IPluginContext *ctx)
310 if ((pf = ctx->GetFunctionByName("OnServerCfg")) != NULL)
315 if ((pf = ctx->GetFunctionByName("OnConfigsExecuted")) != NULL)
321 void SM_ConfigsExecuted_Plugin(unsigned int serial)
323 IPluginIterator *iter = g_PluginSys.GetPluginIterator();
324 while (iter->MorePlugins())
326 CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
327 if (plugin->GetSerial() == serial)
329 SM_DoSingleExecFwds(plugin->GetBaseContext());
337 void SM_ExecuteForPlugin(IPluginContext *ctx)
339 CPlugin *plugin = (CPlugin *)g_PluginSys.GetPluginByCtx(ctx->GetContext());
341 unsigned int num = plugin->GetConfigCount();
344 SM_DoSingleExecFwds(ctx);
346 bool can_create = true;
347 for (unsigned int i=0; i<num; i++)
349 can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
352 UTIL_Format(cmd, sizeof(cmd), "sm internal 2 %d\n", plugin->GetSerial());
353 engine->ServerCommand(cmd);
357 void SM_ExecuteAllConfigs()
364 engine->ServerCommand("exec cfg/sourcemod/sourcemod.cfg\n");
366 IPluginIterator *iter = g_PluginSys.GetPluginIterator();
367 while (iter->MorePlugins())
369 CPlugin *plugin = (CPlugin *)(iter->GetPlugin());
370 unsigned int num = plugin->GetConfigCount();
371 bool can_create = true;
372 for (unsigned int i=0; i<num; i++)
374 can_create = SM_ExecuteConfig(plugin, plugin->GetConfig(i), can_create);
380 engine->ServerCommand("sm internal 1\n");
383 void SM_ConfigsExecuted_Global()
390 g_bConfigsExecd = true;
392 g_pOnServerCfg->Execute(NULL);
393 g_pOnConfigsExecuted->Execute(NULL);