changed the API around a bit to be more flexible

removed some ghastly unneeded stuff from the Translator
added Logger::LogFatal, experimental

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40669
This commit is contained in:
David Anderson 2007-04-05 05:25:11 +00:00
parent 3b9c8e1410
commit f93711bd82
11 changed files with 179 additions and 102 deletions

View File

@ -22,7 +22,7 @@
#ifdef PLATFORM_WINDOWS #ifdef PLATFORM_WINDOWS
ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file"); ConVar sm_corecfgfile("sm_corecfgfile", "addons\\sourcemod\\configs\\core.cfg", 0, "SourceMod core configuration file");
#else #elif defined PLATFORM_LINUX
ConVar sm_corecfgfile("sm_corecfgfile", "addons/sourcemod/configs/core.cfg", 0, "SourceMod core configuration file"); ConVar sm_corecfgfile("sm_corecfgfile", "addons/sourcemod/configs/core.cfg", 0, "SourceMod core configuration file");
#endif #endif
@ -45,21 +45,13 @@ void CoreConfig::OnRootConsoleCommand(const char *command, unsigned int argcount
const char *option = engine->Cmd_Argv(2); const char *option = engine->Cmd_Argv(2);
const char *value = engine->Cmd_Argv(3); const char *value = engine->Cmd_Argv(3);
CoreConfigErr err = SetConfigOption(option, value); char error[255];
switch (err) ConfigResult err = SetConfigOption(option, value, ConfigSource_Console, error, sizeof(error));
if (err == ConfigResult_Reject)
{ {
case CoreConfig_NoRuntime: g_Logger.LogError("Could not set config option \"%s\" to \"%s\" (error: %s)", option, value, error);
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; return;
@ -90,44 +82,39 @@ void CoreConfig::Initialize()
!= SMCParse_Okay) != SMCParse_Okay)
{ {
/* :TODO: This won't actually log or print anything :( - So fix that somehow */ /* :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)); const char *error = g_TextParser.GetSMCErrorString(err);
g_Logger.LogFatal("[SM] Error encountered parsing core config file: %s", error ? error : "");
} }
} }
SMCParseResult CoreConfig::ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes) SMCParseResult CoreConfig::ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes)
{ {
CoreConfigErr err = SetConfigOption(key, value); char error[255];
ConfigResult err = SetConfigOption(key, value, ConfigSource_File, error, sizeof(error));
if (err == CoreConfig_InvalidOption) if (err == ConfigResult_Reject)
{ {
g_Logger.LogError("[SM] Warning: Ignoring invalid option \"%s\" in configuration file.", key); /* This is a fatal error */
} else if (err == CoreConfig_InvalidValue) { g_Logger.LogFatal("%s", error);
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; return SMCParse_Continue;
} }
CoreConfigErr CoreConfig::SetConfigOption(const char *option, const char *value) ConfigResult CoreConfig::SetConfigOption(const char *option, const char *value, ConfigSource source, char *error, size_t maxlength)
{ {
CoreConfigErr err = CoreConfig_TOTAL; ConfigResult result;
CoreConfigErr currentErr;
/* Notify! */ /* Notify! */
SMGlobalClass *pBase = SMGlobalClass::head; SMGlobalClass *pBase = SMGlobalClass::head;
while (pBase) while (pBase)
{ {
currentErr = pBase->OnSourceModConfigChanged(option, value); if ((result = pBase->OnSourceModConfigChanged(option, value, source, error, maxlength)) != ConfigResult_Ignore)
/* Lowest error code has priority */
if (currentErr < err)
{ {
err = currentErr; return result;
} }
pBase = pBase->m_pGlobalClassNext; pBase = pBase->m_pGlobalClassNext;
} }
return err; return ConfigResult_Ignore;
} }

View File

@ -42,7 +42,7 @@ private:
/** /**
* Sets configuration option by notifying SourceMod components that rely on core.cfg * Sets configuration option by notifying SourceMod components that rely on core.cfg
*/ */
CoreConfigErr SetConfigOption(const char *option, const char *value); ConfigResult SetConfigOption(const char *option, const char *value, ConfigSource, char *Error, size_t maxlength);
}; };
extern CoreConfig g_CoreConfig; extern CoreConfig g_CoreConfig;

View File

@ -15,6 +15,7 @@
#include <time.h> #include <time.h>
#include "sourcemod.h" #include "sourcemod.h"
#include "sourcemm_api.h" #include "sourcemm_api.h"
#include "sm_stringutil.h"
#include "Logger.h" #include "Logger.h"
#include "systems/LibrarySys.h" #include "systems/LibrarySys.h"
#include "sm_version.h" #include "sm_version.h"
@ -25,31 +26,39 @@ Logger g_Logger;
* :TODO: This should be creating the log folder if it doesn't exist * :TODO: This should be creating the log folder if it doesn't exist
*/ */
CoreConfigErr Logger::OnSourceModConfigChanged(const char *option, const char *value) ConfigResult Logger::OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength)
{ {
if (strcasecmp(option, "Logging") == 0) if (strcasecmp(key, "Logging") == 0)
{ {
bool state = true; bool state = true;
if (strcasecmp(value, "on") == 0) if (strcasecmp(value, "on") == 0)
{ {
state = true;
} else if (strcasecmp(value, "off") == 0) { } else if (strcasecmp(value, "off") == 0) {
state = false; state = false;
} else { } else {
return CoreConfig_InvalidValue; UTIL_Format(error, maxlength, "Invalid value: must be \"on\" or \"off\"");
return ConfigResult_Reject;
} }
if (m_FirstPass) if (source == ConfigSource_Console)
{ {
m_InitialState = state; if (state && !m_Active)
m_FirstPass = false; {
EnableLogging();
} else if (!state && m_Active) {
DisableLogging();
}
} else { } else {
state ? g_Logger.EnableLogging() : g_Logger.DisableLogging(); m_InitialState = state;
} }
return CoreConfig_Okay; return ConfigResult_Accept;
} else if (strcasecmp(option, "LogMode") == 0) { } else if (strcasecmp(key, "LogMode") == 0) {
if (strcasecmp(value, "daily") == 0) if (strcasecmp(value, "daily") == 0)
{ {
m_Mode = LoggingMode_Daily; m_Mode = LoggingMode_Daily;
@ -58,18 +67,19 @@ CoreConfigErr Logger::OnSourceModConfigChanged(const char *option, const char *v
} else if (strcasecmp(value, "game") == 0) { } else if (strcasecmp(value, "game") == 0) {
m_Mode = LoggingMode_Game; m_Mode = LoggingMode_Game;
} else { } else {
return CoreConfig_InvalidValue; UTIL_Format(error, maxlength, "Invalid value: must be [daily|map|game]");
return ConfigResult_Reject;
} }
return CoreConfig_Okay; return ConfigResult_Accept;
} }
return CoreConfig_InvalidOption; return ConfigResult_Ignore;
} }
void Logger::OnSourceModStartup(bool late) void Logger::OnSourceModStartup(bool late)
{ {
InitLogger(m_Mode, m_InitialState); InitLogger(m_Mode);
} }
void Logger::OnSourceModAllShutdown() void Logger::OnSourceModAllShutdown()
@ -155,10 +165,10 @@ void Logger::_CloseFile()
m_ErrFileName.clear(); m_ErrFileName.clear();
} }
void Logger::InitLogger(LoggingMode mode, bool startlogging) void Logger::InitLogger(LoggingMode mode)
{ {
m_Mode = mode; m_Mode = mode;
m_Active = startlogging; m_Active = m_InitialState;
time_t t; time_t t;
time(&t); time(&t);
@ -173,7 +183,7 @@ void Logger::InitLogger(LoggingMode mode, bool startlogging)
{ {
case LoggingMode_PerMap: case LoggingMode_PerMap:
{ {
if (!startlogging) if (!m_Active)
{ {
m_DelayedStart = true; m_DelayedStart = true;
} }
@ -414,3 +424,24 @@ void Logger::DisableLogging()
LogMessage("Logging disabled manually by user."); LogMessage("Logging disabled manually by user.");
m_Active = false; m_Active = false;
} }
void Logger::LogFatal(const char *msg, ...)
{
char path[PLATFORM_MAX_PATH];
g_SourceMod.BuildPath(Path_Game, path, sizeof(path), "sourcemod_fatal.log");
FILE *fp = fopen(path, "at");
if (!fp)
{
/* We're just doomed, aren't we... */
return;
}
va_list ap;
va_start(ap, msg);
vfprintf(fp, msg, ap);
va_end(ap);
fputs("\n", fp);
fclose(fp);
}

View File

@ -36,18 +36,27 @@ enum LoggingMode
class Logger : public SMGlobalClass class Logger : public SMGlobalClass
{ {
public: public:
Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false), m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false), m_InitialState(true), m_FirstPass(true) {} Logger() : m_Mode(LoggingMode_Daily), m_ErrMapStart(false),
m_Active(false), m_DelayedStart(false), m_DailyPrintHdr(false),
m_InitialState(true)
{
}
public: //SMGlobalClass public: //SMGlobalClass
CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value); ConfigResult OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength);
void OnSourceModStartup(bool late); void OnSourceModStartup(bool late);
void OnSourceModAllShutdown(); void OnSourceModAllShutdown();
public: public:
void InitLogger(LoggingMode mode, bool startlogging); void InitLogger(LoggingMode mode);
void CloseLogger(); void CloseLogger();
void EnableLogging(); void EnableLogging();
void DisableLogging(); void DisableLogging();
void LogMessage(const char *msg, ...); void LogMessage(const char *msg, ...);
void LogError(const char *msg, ...); void LogError(const char *msg, ...);
void LogFatal(const char *msg, ...);
void MapChange(const char *mapname); void MapChange(const char *mapname);
const char *GetLogFileName(LogType type) const; const char *GetLogFileName(LogType type) const;
LoggingMode GetLoggingMode() const; LoggingMode GetLoggingMode() const;
@ -66,7 +75,6 @@ private:
bool m_DelayedStart; bool m_DelayedStart;
bool m_DailyPrintHdr; bool m_DailyPrintHdr;
bool m_InitialState; bool m_InitialState;
bool m_FirstPass;
}; };
extern Logger g_Logger; extern Logger g_Logger;

View File

@ -604,15 +604,30 @@ Translator::~Translator()
delete m_pStringTab; delete m_pStringTab;
} }
CoreConfigErr Translator::OnSourceModConfigChanged(const char *option, const char *value) ConfigResult Translator::OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength)
{ {
if (strcasecmp(option, "ServerLang") == 0) if (strcasecmp(value, "ServerLang") == 0)
{ {
strncopy(m_ServerLangCode, value, sizeof(m_ServerLangCode)); if (source == ConfigSource_Console)
return CoreConfig_Okay; {
unsigned int index;
if (!GetLanguageByCode(value, &index))
{
UTIL_Format(error, maxlength, "Language code \"%s\" is not registered", value);
return ConfigResult_Reject;
}
} }
return CoreConfig_InvalidOption; strncopy(m_ServerLangCode, value, sizeof(m_ServerLangCode));
return ConfigResult_Accept;
}
return ConfigResult_Ignore;
} }
void Translator::OnSourceModAllInitialized() void Translator::OnSourceModAllInitialized()
@ -837,7 +852,20 @@ TransError Translator::CoreTrans(int client,
return Trans_Okay; return Trans_Okay;
} }
const char *Translator::GetServerLanguageCode() const unsigned int Translator::GetServerLanguageCode()
{ {
return m_ServerLangCode; void *serverLang;
/* :TODO: there is absolutely no reason this shouldn't be cached
* I don't even know why it was returning a string originally
*/
if (!sm_trie_retrieve(m_pLCodeLookup, m_ServerLangCode, &serverLang))
{
g_Logger.LogError("Server language was set to bad language \"%s\" -- reverting to English");
strncopy(m_ServerLangCode, "en", sizeof(m_ServerLangCode));
return 0;
}
return (unsigned int)serverLang;
} }

View File

@ -49,6 +49,8 @@ struct Translation
int *fmt_order; /**< Format phrase order. */ int *fmt_order; /**< Format phrase order. */
}; };
#define LANGUAGE_ENGLISH 0
enum TransError enum TransError
{ {
Trans_Okay = 0, Trans_Okay = 0,
@ -100,7 +102,11 @@ public:
Translator(); Translator();
~Translator(); ~Translator();
public: // SMGlobalClass public: // SMGlobalClass
CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value); ConfigResult OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength);
void OnSourceModAllInitialized(); void OnSourceModAllInitialized();
public: // ITextListener_SMC public: // ITextListener_SMC
void ReadSMC_ParseStart(); void ReadSMC_ParseStart();
@ -121,7 +127,7 @@ public:
const char *phrase, const char *phrase,
void **params, void **params,
size_t *outlen=NULL); size_t *outlen=NULL);
const char *GetServerLanguageCode() const; unsigned int GetServerLanguageCode();
private: private:
bool AddLanguage(const char *langcode, const char *description); bool AddLanguage(const char *langcode, const char *description);
private: private:

View File

@ -30,14 +30,17 @@ using namespace SourceMod;
/** /**
* @brief Lists error codes possible from attempting to set a core configuration option. * @brief Lists error codes possible from attempting to set a core configuration option.
*/ */
enum CoreConfigErr enum ConfigResult
{ {
CoreConfig_Okay = 0, /**< No error */ ConfigResult_Accept = 0,
CoreConfig_NoRuntime = 1, /**< Cannot set config option while SourceMod is running */ ConfigResult_Reject = 1,
CoreConfig_InvalidValue = 2, /**< Invalid value specified for config option */ ConfigResult_Ignore = 2
CoreConfig_InvalidOption = 3, /**< Invalid config option specified */ };
/* -------------------- */
CoreConfig_TOTAL /**< Total number of core config error codes */ enum ConfigSource
{
ConfigSource_File = 0,
ConfigSource_Console = 1,
}; };
/** /**
@ -83,9 +86,13 @@ public:
* @note This is called once BEFORE OnSourceModStartup() when SourceMod is loading * @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 * @note It can then be called again when the 'sm config' command is used
*/ */
virtual CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value) virtual ConfigResult OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength)
{ {
return CoreConfig_InvalidOption; return ConfigResult_Ignore;
} }
private: private:
SMGlobalClass *m_pGlobalClassNext; SMGlobalClass *m_pGlobalClassNext;

View File

@ -73,24 +73,9 @@ size_t Translate(char *buffer, size_t maxlen, IPluginContext *pCtx, const char *
try_serverlang: try_serverlang:
if (target == LANG_SERVER) if (target == LANG_SERVER)
{ {
langname = g_Translator.GetServerLanguageCode(); langid = 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())) { } else if ((target >= 1) && (target <= g_Players.GetMaxClients())) {
langname = g_Translator.GetServerLanguageCode(); /* :TODO: read player's lang */ langid = g_Translator.GetServerLanguageCode();
if (!langname || !g_Translator.GetLanguageByCode(langname, &langid))
{
if (langname && !strcmp(langname, "en"))
{
pCtx->ThrowNativeError("Translation failure: English language not found");
goto error_out;
}
target = LANG_SERVER;
goto try_serverlang;
}
} else { } else {
pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Translation failed: invalid client index %d", target); pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Translation failed: invalid client index %d", target);
goto error_out; goto error_out;
@ -102,9 +87,8 @@ try_serverlang:
{ {
target = LANG_SERVER; target = LANG_SERVER;
goto try_serverlang; goto try_serverlang;
} else { } else if (langid != LANGUAGE_ENGLISH) {
if (!g_Translator.GetLanguageByCode("en", &langid) if (!TryTranslation(pl, key, LANGUAGE_ENGLISH, langcount, &pTrans))
|| !TryTranslation(pl, key, langid, langcount, &pTrans))
{ {
pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Language phrase \"%s\" not found", key); pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Language phrase \"%s\" not found", key);
goto error_out; goto error_out;
@ -900,6 +884,19 @@ size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...)
} }
} }
size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list ap)
{
size_t len = vsnprintf(buffer, maxlength, fmt, ap);
if (len >= maxlength)
{
buffer[maxlength - 1] = '\0';
return (maxlength - 1);
} else {
return len;
}
}
char *sm_strdup(const char *str) char *sm_strdup(const char *str)
{ {
char *ptr = new char[strlen(str)+1]; char *ptr = new char[strlen(str)+1];

View File

@ -30,6 +30,7 @@ const char *stristr(const char *str, const char *substr);
unsigned int strncopy(char *dest, const char *src, size_t count); unsigned int strncopy(char *dest, const char *src, size_t count);
size_t gnprintf(char *buffer, size_t maxlen, const char *format, void **args); size_t gnprintf(char *buffer, size_t maxlen, const char *format, void **args);
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...); size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list ap);
char *sm_strdup(const char *str); char *sm_strdup(const char *str);
#endif // _INCLUDE_SOURCEMOD_STRINGUTIL_H_ #endif // _INCLUDE_SOURCEMOD_STRINGUTIL_H_

View File

@ -69,24 +69,32 @@ SourceModBase::SourceModBase()
m_GotBasePath = false; m_GotBasePath = false;
} }
CoreConfigErr SourceModBase::OnSourceModConfigChanged(const char *option, const char *value) ConfigResult SourceModBase::OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength)
{ {
if (strcasecmp(option, "BasePath") == 0) if (strcasecmp(value, "BasePath") == 0)
{ {
if (source == ConfigSource_Console)
{
UTIL_Format(error, maxlength, "Cannot be set at runtime");
return ConfigResult_Reject;
}
if (!m_GotBasePath) if (!m_GotBasePath)
{ {
g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/%s", g_BaseDir.c_str(), value); g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/%s", g_BaseDir.c_str(), value);
g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), value); g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), value);
m_GotBasePath = true; m_GotBasePath = true;
return CoreConfig_Okay;
} else {
return CoreConfig_NoRuntime;
}
} }
return CoreConfig_InvalidOption; return ConfigResult_Accept;
}
return ConfigResult_Ignore;
} }
bool SourceModBase::InitializeSourceMod(char *error, size_t err_max, bool late) bool SourceModBase::InitializeSourceMod(char *error, size_t err_max, bool late)
@ -97,7 +105,7 @@ bool SourceModBase::InitializeSourceMod(char *error, size_t err_max, bool late)
g_CoreConfig.Initialize(); g_CoreConfig.Initialize();
/* This shouldn't happen, but can't hurt to be safe */ /* This shouldn't happen, but can't hurt to be safe */
if (!m_GotBasePath || !g_LibSys.PathExists(m_SMBaseDir)) if (!g_LibSys.PathExists(m_SMBaseDir) || !m_GotBasePath)
{ {
g_LibSys.PathFormat(m_SMBaseDir, sizeof(m_SMBaseDir), "%s/addons/sourcemod", g_BaseDir.c_str()); 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"); g_LibSys.PathFormat(m_SMRelDir, sizeof(m_SMRelDir), "addons/sourcemod");

View File

@ -78,7 +78,11 @@ public:
*/ */
void SetAuthChecking(bool set); void SetAuthChecking(bool set);
public: // SMGlobalClass public: // SMGlobalClass
CoreConfigErr OnSourceModConfigChanged(const char *option, const char *value); ConfigResult OnSourceModConfigChanged(const char *key,
const char *value,
ConfigSource source,
char *error,
size_t maxlength);
public: // ISourceMod public: // ISourceMod
const char *GetModPath() const; const char *GetModPath() const;
const char *GetSourceModPath() const; const char *GetSourceModPath() const;