Ugh, initial import of core config file stuff

Warning: This is positively terrible code.
It works, but needs A LOT of work still :\

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40667
This commit is contained in:
Scott Ehlert 2007-04-05 03:02:00 +00:00
parent af77decdab
commit ddfe6d84d6
12 changed files with 368 additions and 27 deletions

12
configs/core.cfg Normal file
View File

@ -0,0 +1,12 @@
"Core"
{
"BasePath" "addons/sourcemod"
"Logging" "on"
"LogMode" "daily"
"ServerLang" "en"
"InvalidOpt" "hello"
}

133
core/CoreConfig.cpp Normal file
View File

@ -0,0 +1,133 @@
/**
* vim: set ts=4 :
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is not open source and may not be copied without explicit
* written permission of AlliedModders LLC. This file may not be redistributed
* in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#include "CoreConfig.h"
#include "sourcemod.h"
#include "sourcemm_api.h"
#include "sm_srvcmds.h"
#include "LibrarySys.h"
#include "TextParsers.h"
#include "Logger.h"
#ifdef PLATFORM_WINDOWS
ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
#else
ConVar sm_corecfgfile("sm_corecfgfile", "addons/sourcemod/configs/core.cfg", 0, "SourceMod core configuration file");
#endif
CoreConfig g_CoreConfig;
void CoreConfig::OnSourceModAllInitialized()
{
g_RootMenu.AddRootConsoleCommand("config", "Set core configuration options", this);
}
void CoreConfig::OnSourceModShutdown()
{
g_RootMenu.RemoveRootConsoleCommand("config", this);
}
void CoreConfig::OnRootConsoleCommand(const char *command, unsigned int argcount)
{
if (argcount >= 4)
{
const char *option = engine->Cmd_Argv(2);
const char *value = engine->Cmd_Argv(3);
CoreConfigErr err = SetConfigOption(option, value);
switch (err)
{
case CoreConfig_NoRuntime:
g_RootMenu.ConsolePrint("[SM] Cannot set \"%s\" while SourceMod is running.", option);
break;
case CoreConfig_InvalidValue:
g_RootMenu.ConsolePrint("[SM] Invalid value \"%s\" specified for configuration option \"%s\"", value, option);
break;
case CoreConfig_InvalidOption:
g_RootMenu.ConsolePrint("[SM] Invalid configuration option specified: %s", option);
break;
default:
break;
}
return;
}
g_RootMenu.ConsolePrint("[SM] Usage: sm config <option> <value>");
}
void CoreConfig::Initialize()
{
SMCParseError err;
char filePath[PLATFORM_MAX_PATH];
/* Try to get command line value of core config convar */
const char *corecfg = icvar->GetCommandLineValue("sm_corecfgfile");
/* If sm_corecfgfile not specified on command line, use default value */
if (!corecfg)
{
corecfg = sm_corecfgfile.GetDefault();
}
/* Format path to config file */
g_LibSys.PathFormat(filePath, sizeof(filePath), "%s/%s", g_SourceMod.GetModPath(), corecfg);
/* Parse config file */
if ((err=g_TextParser.ParseFile_SMC(filePath, this, NULL, NULL))
!= SMCParse_Okay)
{
/* :TODO: This won't actually log or print anything :( - So fix that somehow */
g_Logger.LogError("[SM] Error encountered parsing core config file: %s", g_TextParser.GetSMCErrorString(err));
}
}
SMCParseResult CoreConfig::ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes)
{
CoreConfigErr err = SetConfigOption(key, value);
if (err == CoreConfig_InvalidOption)
{
g_Logger.LogError("[SM] Warning: Ignoring invalid option \"%s\" in configuration file.", key);
} else if (err == CoreConfig_InvalidValue) {
g_Logger.LogError("[SM] Warning encountered parsing core configuration file.");
g_Logger.LogError("[SM] Invalid value \"%s\" specified for option \"%s\"", value, key);
}
return SMCParse_Continue;
}
CoreConfigErr CoreConfig::SetConfigOption(const char *option, const char *value)
{
CoreConfigErr err = CoreConfig_TOTAL;
CoreConfigErr currentErr;
/* Notify! */
SMGlobalClass *pBase = SMGlobalClass::head;
while (pBase)
{
currentErr = pBase->OnSourceModConfigChanged(option, value);
/* Lowest error code has priority */
if (currentErr < err)
{
err = currentErr;
}
pBase = pBase->m_pGlobalClassNext;
}
return err;
}

50
core/CoreConfig.h Normal file
View File

@ -0,0 +1,50 @@
/**
* vim: set ts=4 :
* ===============================================================
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
* ===============================================================
*
* This file is not open source and may not be copied without explicit
* written permission of AlliedModders LLC. This file may not be redistributed
* in whole or significant part.
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_CORECONFIG_H_
#define _INCLUDE_SOURCEMOD_CORECONFIG_H_
#include "sm_globals.h"
#include <ITextParsers.h>
#include <IRootConsoleMenu.h>
using namespace SourceMod;
class CoreConfig :
public SMGlobalClass,
public ITextListener_SMC,
public IRootConsoleCommand
{
public: // SMGlobalClass
void OnSourceModAllInitialized();
void OnSourceModShutdown();
public: // ITextListener_SMC
SMCParseResult ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes);
public: // IRootConsoleCommand
void OnRootConsoleCommand(const char *command, unsigned int argcount);
public:
/**
* Initializes CoreConfig by reading from core.cfg file
*/
void Initialize();
private:
/**
* Sets configuration option by notifying SourceMod components that rely on core.cfg
*/
CoreConfigErr SetConfigOption(const char *option, const char *value);
};
extern CoreConfig g_CoreConfig;
#endif // _INCLUDE_SOURCEMOD_CORECONFIG_H_

View File

@ -25,10 +25,51 @@ Logger g_Logger;
* :TODO: This should be creating the log folder if it doesn't exist
*/
CoreConfigErr Logger::OnSourceModConfigChanged(const char *option, const char *value)
{
if (strcasecmp(option, "Logging") == 0)
{
bool state = true;
if (strcasecmp(value, "on") == 0)
{
state = true;
} else if (strcasecmp(value, "off") == 0) {
state = false;
} else {
return CoreConfig_InvalidValue;
}
if (m_FirstPass)
{
m_InitialState = state;
m_FirstPass = false;
} else {
state ? g_Logger.EnableLogging() : g_Logger.DisableLogging();
}
return CoreConfig_Okay;
} else if (strcasecmp(option, "LogMode") == 0) {
if (strcasecmp(value, "daily") == 0)
{
m_Mode = LoggingMode_Daily;
} else if (strcasecmp(value, "map") == 0) {
m_Mode = LoggingMode_PerMap;
} else if (strcasecmp(value, "game") == 0) {
m_Mode = LoggingMode_Game;
} else {
return CoreConfig_InvalidValue;
}
return CoreConfig_Okay;
}
return CoreConfig_InvalidOption;
}
void Logger::OnSourceModStartup(bool late)
{
//:TODO: read these options from a file, dont hardcode them
InitLogger(LoggingMode_Daily, true);
InitLogger(m_Mode, m_InitialState);
}
void Logger::OnSourceModAllShutdown()
@ -42,6 +83,9 @@ void Logger::_NewMapFile()
{
return;
}
/* Append "Log file closed" to previous log file */
_CloseFile();
char _filename[256];
int i = 0;
@ -113,7 +157,7 @@ void Logger::_CloseFile()
void Logger::InitLogger(LoggingMode mode, bool startlogging)
{
m_mode = mode;
m_Mode = mode;
m_Active = startlogging;
time_t t;
@ -125,7 +169,7 @@ void Logger::InitLogger(LoggingMode mode, bool startlogging)
g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%02d%02d%02d.log", curtime->tm_mon + 1, curtime->tm_mday, curtime->tm_year - 100);
m_ErrFileName.assign(_filename);
switch (m_mode)
switch (m_Mode)
{
case LoggingMode_PerMap:
{
@ -162,11 +206,11 @@ void Logger::LogMessage(const char *vafmt, ...)
return;
}
if (m_mode == LoggingMode_HL2)
if (m_Mode == LoggingMode_Game)
{
va_list ap;
va_start(ap, vafmt);
_PrintToHL2Log(vafmt, ap);
_PrintToGameLog(vafmt, ap);
va_end(ap);
return;
}
@ -190,7 +234,7 @@ void Logger::LogMessage(const char *vafmt, ...)
strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime);
FILE *fp = NULL;
if (m_mode == LoggingMode_PerMap)
if (m_Mode == LoggingMode_PerMap)
{
fp = fopen(m_NrmFileName.c_str(), "a+");
if (!fp)
@ -287,7 +331,7 @@ void Logger::MapChange(const char *mapname)
{
m_CurMapName.assign(mapname);
switch (m_mode)
switch (m_Mode)
{
case LoggingMode_Daily:
{
@ -313,7 +357,7 @@ void Logger::MapChange(const char *mapname)
m_ErrMapStart = false;
}
void Logger::_PrintToHL2Log(const char *fmt, va_list ap)
void Logger::_PrintToGameLog(const char *fmt, va_list ap)
{
char msg[3072];
size_t len;
@ -348,7 +392,7 @@ const char *Logger::GetLogFileName(LogType type) const
LoggingMode Logger::GetLoggingMode() const
{
return m_mode;
return m_Mode;
}
void Logger::EnableLogging()

View File

@ -30,14 +30,15 @@ enum LoggingMode
{
LoggingMode_Daily,
LoggingMode_PerMap,
LoggingMode_HL2
LoggingMode_Game
};
class Logger : public SMGlobalClass
{
public:
Logger() : m_ErrMapStart(false), m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false) {}
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false), m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false), m_InitialState(true), m_FirstPass(true) {}
public: //SMGlobalClass
CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value);
void OnSourceModStartup(bool late);
void OnSourceModAllShutdown();
public:
@ -53,17 +54,19 @@ public:
private:
void _CloseFile();
void _NewMapFile();
void _PrintToHL2Log(const char *fmt, va_list ap);
void _PrintToGameLog(const char *fmt, va_list ap);
private:
String m_NrmFileName;
String m_ErrFileName;
String m_CurMapName;
LoggingMode m_mode;
LoggingMode m_Mode;
int m_CurDay;
bool m_ErrMapStart;
bool m_Active;
bool m_DelayedStart;
bool m_DailyPrintHdr;
bool m_InitialState;
bool m_FirstPass;
};
extern Logger g_Logger;

View File

@ -584,6 +584,7 @@ Translator::Translator()
{
m_pStringTab = new BaseStringTable(2048);
m_pLCodeLookup = sm_trie_create();
strncopy(m_ServerLangCode, "en", sizeof(m_ServerLangCode));
}
Translator::~Translator()
@ -603,6 +604,17 @@ Translator::~Translator()
delete m_pStringTab;
}
CoreConfigErr Translator::OnSourceModConfigChanged(const char *option, const char *value)
{
if (strcasecmp(option, "ServerLang") == 0)
{
strncopy(m_ServerLangCode, value, sizeof(m_ServerLangCode));
return CoreConfig_Okay;
}
return CoreConfig_InvalidOption;
}
void Translator::OnSourceModAllInitialized()
{
AddLanguage("en", "English");
@ -801,9 +813,16 @@ TransError Translator::CoreTrans(int client,
return Trans_BadPhraseFile;
}
/* Using server lang temporarily until client lang stuff is implemented */
unsigned int serverLang;
if (!sm_trie_retrieve(m_pLCodeLookup, m_ServerLangCode, (void **)&serverLang))
{
return Trans_BadLanguage;
}
Translation trans;
TransError err;
if ((err=g_pCorePhrases->GetTranslation(phrase, 0, &trans)) != Trans_Okay)
if ((err=g_pCorePhrases->GetTranslation(phrase, serverLang, &trans)) != Trans_Okay)
{
return err;
}
@ -817,3 +836,8 @@ TransError Translator::CoreTrans(int client,
return Trans_Okay;
}
const char *Translator::GetServerLanguageCode() const
{
return m_ServerLangCode;
}

View File

@ -99,9 +99,10 @@ class Translator :
public:
Translator();
~Translator();
public: //SMGlobalClass
public: // SMGlobalClass
CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value);
void OnSourceModAllInitialized();
public: //ITextListener_SMC
public: // ITextListener_SMC
void ReadSMC_ParseStart();
SMCParseResult ReadSMC_NewSection(const char *name, bool opt_quotes);
SMCParseResult ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes);
@ -120,6 +121,7 @@ public:
const char *phrase,
void **params,
size_t *outlen=NULL);
const char *GetServerLanguageCode() const;
private:
bool AddLanguage(const char *langcode, const char *description);
private:
@ -129,6 +131,7 @@ private:
Trie *m_pLCodeLookup;
bool m_InLanguageSection;
String m_CustomError;
char m_ServerLangCode[3];
};
extern CPhraseFile *g_pCorePhrases;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Version="8.00"
Name="sourcemod_mm"
ProjectGUID="{E39527CD-7CAB-4420-97CC-DA1B93B260BC}"
RootNamespace="sourcemod_mm"
@ -195,6 +195,10 @@
RelativePath="..\ConVarManager.cpp"
>
</File>
<File
RelativePath="..\CoreConfig.cpp"
>
</File>
<File
RelativePath="..\DebugReporter.cpp"
>
@ -289,6 +293,10 @@
RelativePath="..\ConVarManager.h"
>
</File>
<File
RelativePath="..\CoreConfig.h"
>
</File>
<File
RelativePath="..\DebugReporter.h"
>

View File

@ -27,12 +27,26 @@
using namespace SourcePawn;
using namespace SourceMod;
/**
* @brief Lists error codes possible from attempting to set a core configuration option.
*/
enum CoreConfigErr
{
CoreConfig_Okay = 0, /**< No error */
CoreConfig_NoRuntime = 1, /**< Cannot set config option while SourceMod is running */
CoreConfig_InvalidValue = 2, /**< Invalid value specified for config option */
CoreConfig_InvalidOption = 3, /**< Invalid config option specified */
/* -------------------- */
CoreConfig_TOTAL /**< Total number of core config error codes */
};
/**
* @brief Any class deriving from this will be automatically initiated/shutdown by SourceMod
*/
class SMGlobalClass
{
friend class SourceModBase;
friend class CoreConfig;
public:
SMGlobalClass();
public:
@ -58,11 +72,21 @@ public:
}
/**
* @brief Called after SourceMod is completely shut down
*/
* @brief Called after SourceMod is completely shut down
*/
virtual void OnSourceModAllShutdown()
{
}
/**
* @brief Called when a core config option is changed.
* @note This is called once BEFORE OnSourceModStartup() when SourceMod is loading
* @note It can then be called again when the 'sm config' command is used
*/
virtual CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value)
{
return CoreConfig_InvalidOption;
}
private:
SMGlobalClass *m_pGlobalClassNext;
static SMGlobalClass *head;

View File

@ -62,7 +62,7 @@ inline bool TryTranslation(CPlugin *pl, const char *key, unsigned int langid, un
size_t Translate(char *buffer, size_t maxlen, IPluginContext *pCtx, const char *key, cell_t target, const cell_t *params, int *arg, bool *error)
{
unsigned int langid;
char *langname = NULL;
const char *langname = NULL;
*error = false;
Translation pTrans;
CPlugin *pl = (CPlugin *)g_PluginSys.FindPluginByContext(pCtx->GetContext());
@ -73,14 +73,14 @@ size_t Translate(char *buffer, size_t maxlen, IPluginContext *pCtx, const char *
try_serverlang:
if (target == LANG_SERVER)
{
langname = "en"; //:TODO: read serverlang
langname = g_Translator.GetServerLanguageCode();
if (!TryServerLanguage(langname ? langname : "en", &langid))
{
pCtx->ThrowNativeError("Translation failure: English language not found");
goto error_out;
}
} else if ((target >= 1) && (target <= g_Players.GetMaxClients())) {
langname = "en"; //:TODO: read player's lang
langname = g_Translator.GetServerLanguageCode(); /* :TODO: read player's lang */
if (!langname || !g_Translator.GetLanguageByCode(langname, &langid))
{
if (langname && !strcmp(langname, "en"))

View File

@ -20,6 +20,7 @@
#include <sh_string.h>
#include "PluginSys.h"
#include "ShareSys.h"
#include "CoreConfig.h"
#include "Logger.h"
#include "ExtensionSys.h"
#include "AdminCache.h"
@ -65,13 +66,43 @@ SourceModBase::SourceModBase()
{
m_IsMapLoading = false;
m_ExecPluginReload = false;
m_GotBasePath = false;
}
CoreConfigErr SourceModBase::OnSourceModConfigChanged(const char *option, const char *value)
{
if (strcasecmp(option, "BasePath") == 0)
{
if (!m_GotBasePath)
{
g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/%s", g_BaseDir.c_str(), value);
g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), value);
m_GotBasePath = true;
return CoreConfig_Okay;
} else {
return CoreConfig_NoRuntime;
}
}
return CoreConfig_InvalidOption;
}
bool SourceModBase::InitializeSourceMod(char *error, size_t err_max, bool late)
{
g_BaseDir.assign(g_SMAPI->GetBaseDir());
g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/addons/sourcemod", g_BaseDir.c_str());
g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), "addons/sourcemod");
/* Initialize CoreConfig so we can get SourceMod base path properly - this basically parses core.cfg */
g_CoreConfig.Initialize();
/* This shouldn't happen, but can't hurt to be safe */
if (!m_GotBasePath || !g_LibSys.PathExists(m_SMBaseDir))
{
g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/addons/sourcemod", g_BaseDir.c_str());
g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), "addons/sourcemod");
m_GotBasePath = true;
}
/* Attempt to load the JIT! */
char file[PLATFORM_MAX_PATH];

View File

@ -26,7 +26,9 @@ using namespace SourceHook;
* @brief Implements SourceMod's global overall management, API, and logic
*/
class SourceModBase : public ISourceMod
class SourceModBase :
public ISourceMod,
public SMGlobalClass
{
public:
SourceModBase();
@ -75,7 +77,9 @@ public:
* @brief Sets whether if SoureMod needs to check player auths.
*/
void SetAuthChecking(bool set);
public: //ISourceMod
public: // SMGlobalClass
CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value);
public: // ISourceMod
const char *GetModPath() const;
const char *GetSourceModPath() const;
size_t BuildPath(PathType type, char *buffer, size_t maxlength, char *format, ...);
@ -90,6 +94,10 @@ private:
* @brief Loading plugins
*/
void DoGlobalPluginLoads();
/**
* @brief GameFrame hook
*/
void GameFrame(bool simulating);
private:
CStack<CDataPack *> m_freepacks;
@ -99,6 +107,7 @@ private:
bool m_ExecPluginReload;
unsigned int m_target;
bool m_CheckingAuth;
bool m_GotBasePath;
};
extern SourceModBase g_SourceMod;