/** * MaNGOS is a full featured server for World of Warcraft, supporting * the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8 * * Copyright (C) 2005-2016 MaNGOS project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * World of Warcraft, and all World of Warcraft or Warcraft art, images, * and lore are copyrighted by Blizzard Entertainment, Inc. */ #include "Common/Common.h" #include "Log.h" #include "Policies/Singleton.h" #include "Config/Config.h" #include "Utilities/Util.h" #include "Utilities/ByteBuffer.h" #include "Utilities/ProgressBar.h" #include #include #include #include INSTANTIATE_SINGLETON_1(Log); LogFilterData logFilterData[LOG_FILTER_COUNT] = { { "transport_moves", "LogFilter_TransportMoves", true }, { "creature_moves", "LogFilter_CreatureMoves", true }, { "visibility_changes", "LogFilter_VisibilityChanges", true }, { "", "", true }, { "weather", "LogFilter_Weather", true }, { "player_stats", "LogFilter_PlayerStats", false }, { "sql_text", "LogFilter_SQLText", true }, { "player_moves", "LogFilter_PlayerMoves", true }, { "periodic_effects", "LogFilter_PeriodicAffects", false }, { "ai_and_movegens", "LogFilter_AIAndMovegens", false }, { "damage", "LogFilter_Damage", false }, { "combat", "LogFilter_Combat", false }, { "spell_cast", "LogFilter_SpellCast", false }, { "db_stricted_check", "LogFilter_DbStrictedCheck", true }, { "ahbot_seller", "LogFilter_AhbotSeller", true }, { "ahbot_buyer", "LogFilter_AhbotBuyer", true }, { "pathfinding", "LogFilter_Pathfinding", true }, { "map_loading", "LogFilter_MapLoading", true }, { "event_ai_dev", "LogFilter_EventAiDev", true }, }; enum LogType { LogNormal = 0, LogDetails, LogDebug, LogError }; const int LogType_count = int(LogError) + 1; Log::Log() : raLogfile(NULL), logfile(NULL), gmLogfile(NULL), charLogfile(NULL), dberLogfile(NULL), #ifdef ENABLE_ELUNA elunaErrLogfile(NULL), #endif /* ENABLE_ELUNA */ eventAiErLogfile(NULL), scriptErrLogFile(NULL), worldLogfile(NULL), wardenLogfile(NULL), m_colored(false), m_includeTime(false), m_gmlog_per_account(false), m_scriptLibName(NULL) { Initialize(); } void Log::InitColors(const std::string& str) { if (str.empty()) { m_colored = false; return; } int color[4]; std::istringstream ss(str); for (int i = 0; i < LogType_count; ++i) { ss >> color[i]; if (!ss) { return; } if (color[i] < 0 || color[i] >= Color_count) { return; } } for (int i = 0; i < LogType_count; ++i) { m_colors[i] = Color(color[i]); } m_colored = true; } void Log::SetColor(bool stdout_stream, Color color) { #if PLATFORM == PLATFORM_WINDOWS static WORD WinColorFG[Color_count] = { 0, // BLACK FOREGROUND_RED, // RED FOREGROUND_GREEN, // GREEN FOREGROUND_RED | FOREGROUND_GREEN, // BROWN FOREGROUND_BLUE, // BLUE FOREGROUND_RED | FOREGROUND_BLUE,// MAGENTA FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,// WHITE // YELLOW FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, // RED_BOLD FOREGROUND_RED | FOREGROUND_INTENSITY, // GREEN_BOLD FOREGROUND_GREEN | FOREGROUND_INTENSITY, FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD // MAGENTA_BOLD FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, // CYAN_BOLD FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, // WHITE_BOLD FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY }; HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); SetConsoleTextAttribute(hConsole, WinColorFG[color]); #else enum ANSITextAttr { TA_NORMAL = 0, TA_BOLD = 1, TA_BLINK = 5, TA_REVERSE = 7 }; enum ANSIFgTextAttr { FG_BLACK = 30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE, FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW }; enum ANSIBgTextAttr { BG_BLACK = 40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE, BG_MAGENTA, BG_CYAN, BG_WHITE }; static uint8 UnixColorFG[Color_count] = { FG_BLACK, // BLACK FG_RED, // RED FG_GREEN, // GREEN FG_BROWN, // BROWN FG_BLUE, // BLUE FG_MAGENTA, // MAGENTA FG_CYAN, // CYAN FG_WHITE, // WHITE FG_YELLOW, // YELLOW FG_RED, // LRED FG_GREEN, // LGREEN FG_BLUE, // LBLUE FG_MAGENTA, // LMAGENTA FG_CYAN, // LCYAN FG_WHITE // LWHITE }; fprintf((stdout_stream ? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < Color_count ? ";1" : "")); #endif } void Log::ResetColor(bool stdout_stream) { #if PLATFORM == PLATFORM_WINDOWS HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); #else fprintf((stdout_stream ? stdout : stderr), "\x1b[0m"); #endif } void Log::SetLogLevel(char* level) { int32 newLevel = atoi((char*)level); if (newLevel < LOG_LVL_MINIMAL) { newLevel = LOG_LVL_MINIMAL; } else if (newLevel > LOG_LVL_DEBUG) { newLevel = LOG_LVL_DEBUG; } m_logLevel = LogLevel(newLevel); printf("LogLevel is %u\n", m_logLevel); } void Log::SetLogFileLevel(char* level) { int32 newLevel = atoi((char*)level); if (newLevel < LOG_LVL_MINIMAL) { newLevel = LOG_LVL_MINIMAL; } else if (newLevel > LOG_LVL_DEBUG) { newLevel = LOG_LVL_DEBUG; } m_logFileLevel = LogLevel(newLevel); printf("LogFileLevel is %u\n", m_logFileLevel); } void Log::Initialize() { /// Common log files data m_logsDir = sConfig.GetStringDefault("LogsDir", ""); if (!m_logsDir.empty()) { if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\')) { m_logsDir.append("/"); } } m_logsTimestamp = "_" + GetTimestampStr(); /// Open specific log files logfile = openLogFile("LogFile", "LogTimestamp", "w"); m_gmlog_per_account = sConfig.GetBoolDefault("GmLogPerAccount", false); if (!m_gmlog_per_account) { gmLogfile = openLogFile("GMLogFile", "GmLogTimestamp", "a"); } else { // GM log settings for per account case m_gmlog_filename_format = sConfig.GetStringDefault("GMLogFile", ""); if (!m_gmlog_filename_format.empty()) { bool m_gmlog_timestamp = sConfig.GetBoolDefault("GmLogTimestamp", false); size_t dot_pos = m_gmlog_filename_format.find_last_of("."); if (dot_pos != m_gmlog_filename_format.npos) { if (m_gmlog_timestamp) { m_gmlog_filename_format.insert(dot_pos, m_logsTimestamp); } m_gmlog_filename_format.insert(dot_pos, "_#%u"); } else { m_gmlog_filename_format += "_#%u"; if (m_gmlog_timestamp) { m_gmlog_filename_format += m_logsTimestamp; } } m_gmlog_filename_format = m_logsDir + m_gmlog_filename_format; } } charLogfile = openLogFile("CharLogFile", "CharLogTimestamp", "a"); dberLogfile = openLogFile("DBErrorLogFile", NULL, "a"); #ifdef ENABLE_ELUNA elunaErrLogfile = openLogFile("ElunaErrorLogFile", NULL, "a"); #endif /* ENABLE_ELUNA */ eventAiErLogfile = openLogFile("EventAIErrorLogFile", NULL, "a"); raLogfile = openLogFile("RaLogFile", NULL, "a"); worldLogfile = openLogFile("WorldLogFile", "WorldLogTimestamp", "a"); wardenLogfile = openLogFile("WardenLogFile", "WardenLogTimestamp", "a"); // Main log file settings m_includeTime = sConfig.GetBoolDefault("LogTime", false); m_logLevel = LogLevel(sConfig.GetIntDefault("LogLevel", 0)); m_logFileLevel = LogLevel(sConfig.GetIntDefault("LogFileLevel", 0)); InitColors(sConfig.GetStringDefault("LogColors", "")); m_logFilter = 0; for (int i = 0; i < LOG_FILTER_COUNT; ++i) if (*logFilterData[i].name) if (sConfig.GetBoolDefault(logFilterData[i].configName, logFilterData[i].defaultState)) { m_logFilter |= (1 << i); } // Char log settings m_charLog_Dump = sConfig.GetBoolDefault("CharLogDump", false); } FILE* Log::openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode) { std::string logfn = sConfig.GetStringDefault(configFileName, ""); if (logfn.empty()) { return NULL; } if (configTimeStampFlag && sConfig.GetBoolDefault(configTimeStampFlag, false)) { size_t dot_pos = logfn.find_last_of("."); if (dot_pos != logfn.npos) { logfn.insert(dot_pos, m_logsTimestamp); } else { logfn += m_logsTimestamp; } } return fopen((m_logsDir + logfn).c_str(), mode); } FILE* Log::openGmlogPerAccount(uint32 account) { if (m_gmlog_filename_format.empty()) { return NULL; } char namebuf[MANGOS_PATH_MAX]; snprintf(namebuf, MANGOS_PATH_MAX, m_gmlog_filename_format.c_str(), account); return fopen(namebuf, "a"); } void Log::outTimestamp(FILE* file) { time_t t = time(NULL); tm* aTm = localtime(&t); // YYYY year // MM month (2 digits 01-12) // DD day (2 digits 01-31) // HH hour (2 digits 00-23) // MM minutes (2 digits 00-59) // SS seconds (2 digits 00-59) fprintf(file, "%-4d-%02d-%02d %02d:%02d:%02d ", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec); } void Log::outTime() { time_t t = time(NULL); tm* aTm = localtime(&t); // YYYY year // MM month (2 digits 01-12) // DD day (2 digits 01-31) // HH hour (2 digits 00-23) // MM minutes (2 digits 00-59) // SS seconds (2 digits 00-59) printf("%02d:%02d:%02d ", aTm->tm_hour, aTm->tm_min, aTm->tm_sec); } std::string Log::GetTimestampStr() { time_t t = time(NULL); tm* aTm = localtime(&t); // YYYY year // MM month (2 digits 01-12) // DD day (2 digits 01-31) // HH hour (2 digits 00-23) // MM minutes (2 digits 00-59) // SS seconds (2 digits 00-59) char buf[20]; snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec); return std::string(buf); } void Log::outString() { if (m_includeTime) { outTime(); } printf("\n"); if (logfile) { outTimestamp(logfile); fprintf(logfile, "\n"); fflush(logfile); } fflush(stdout); } void Log::outString(const char* str, ...) { if (!str) { return; } if (m_colored) { SetColor(true, m_colors[LogNormal]); } if (m_includeTime) { outTime(); } va_list ap; va_start(ap, str); vutf8printf(stdout, str, &ap); va_end(ap); if (m_colored) { ResetColor(true); } printf("\n"); if (logfile) { outTimestamp(logfile); va_start(ap, str); vfprintf(logfile, str, ap); fprintf(logfile, "\n"); va_end(ap); fflush(logfile); } fflush(stdout); } void Log::outError(const char* err, ...) { if (!err) { return; } if (m_colored) { SetColor(false, m_colors[LogError]); } if (m_includeTime) { outTime(); } va_list ap; va_start(ap, err); vutf8printf(stderr, err, &ap); va_end(ap); if (m_colored) { ResetColor(false); } fprintf(stderr, "\n"); if (logfile) { outTimestamp(logfile); fprintf(logfile, "ERROR:"); va_start(ap, err); vfprintf(logfile, err, ap); va_end(ap); fprintf(logfile, "\n"); fflush(logfile); } fflush(stderr); } void Log::outErrorDb() { if (m_includeTime) { outTime(); } fprintf(stderr, "\n"); if (logfile) { outTimestamp(logfile); fprintf(logfile, "ERROR:\n"); fflush(logfile); } if (dberLogfile) { outTimestamp(dberLogfile); fprintf(dberLogfile, "\n"); fflush(dberLogfile); } fflush(stderr); } void Log::outErrorDb(const char* err, ...) { if (!err) { return; } if (m_colored) { SetColor(false, m_colors[LogError]); } if (m_includeTime) { outTime(); } va_list ap; va_start(ap, err); vutf8printf(stderr, err, &ap); va_end(ap); if (m_colored) { ResetColor(false); } fprintf(stderr, "\n"); if (logfile) { outTimestamp(logfile); fprintf(logfile, "ERROR:"); va_start(ap, err); vfprintf(logfile, err, ap); va_end(ap); fprintf(logfile, "\n"); fflush(logfile); } if (dberLogfile) { outTimestamp(dberLogfile); va_list ap; va_start(ap, err); vfprintf(dberLogfile, err, ap); va_end(ap); fprintf(dberLogfile, "\n"); fflush(dberLogfile); } fflush(stderr); } #ifdef ENABLE_ELUNA void Log::outErrorEluna() { if (m_includeTime) outTime(); fprintf(stderr, "\n"); if (logfile) { outTimestamp(logfile); fprintf(logfile, "ERROR Eluna\n"); fflush(logfile); } if (elunaErrLogfile) { outTimestamp(elunaErrLogfile); fprintf(elunaErrLogfile, "\n"); fflush(elunaErrLogfile); } fflush(stderr); } #else /* This is made to not fiddle with the eluna code in LuaEngine/ at all */ void Log::outErrorEluna() {} #endif /* ENABLE_ELUNA */ #ifdef ENABLE_ELUNA void Log::outErrorEluna(const char* err, ...) { if (!err) return; if (m_colored) SetColor(false, m_colors[LogError]); if (m_includeTime) outTime(); va_list ap; va_start(ap, err); vutf8printf(stderr, err, &ap); va_end(ap); if (m_colored) ResetColor(false); fprintf(stderr, "\n"); if (logfile) { outTimestamp(logfile); fprintf(logfile, "ERROR Eluna: "); va_start(ap, err); vfprintf(logfile, err, ap); va_end(ap); fprintf(logfile, "\n"); fflush(logfile); } if (elunaErrLogfile) { outTimestamp(elunaErrLogfile); va_list ap; va_start(ap, err); vfprintf(elunaErrLogfile, err, ap); va_end(ap); fprintf(elunaErrLogfile, "\n"); fflush(elunaErrLogfile); } fflush(stderr); } #else /* This is made to not fiddle with the eluna code in LuaEngine/ at all */ void Log::outErrorEluna(const char* err, ...) {} #endif /* ENABLE_ELUNA */ void Log::outErrorEventAI() { if (m_includeTime) { outTime(); } fprintf(stderr, "\n"); if (logfile) { outTimestamp(logfile); fprintf(logfile, "ERROR CreatureEventAI\n"); fflush(logfile); } if (eventAiErLogfile) { outTimestamp(eventAiErLogfile); fprintf(eventAiErLogfile, "\n"); fflush(eventAiErLogfile); } fflush(stderr); } void Log::outErrorEventAI(const char* err, ...) { if (!err) { return; } if (m_colored) { SetColor(false, m_colors[LogError]); } if (m_includeTime) { outTime(); } va_list ap; va_start(ap, err); vutf8printf(stderr, err, &ap); va_end(ap); if (m_colored) { ResetColor(false); } fprintf(stderr, "\n"); if (logfile) { outTimestamp(logfile); fprintf(logfile, "ERROR CreatureEventAI: "); va_start(ap, err); vfprintf(logfile, err, ap); va_end(ap); fprintf(logfile, "\n"); fflush(logfile); } if (eventAiErLogfile) { outTimestamp(eventAiErLogfile); va_list ap; va_start(ap, err); vfprintf(eventAiErLogfile, err, ap); va_end(ap); fprintf(eventAiErLogfile, "\n"); fflush(eventAiErLogfile); } fflush(stderr); } void Log::outBasic(const char* str, ...) { if (!str) { return; } if (m_logLevel >= LOG_LVL_BASIC) { if (m_colored) { SetColor(true, m_colors[LogDetails]); } if (m_includeTime) { outTime(); } va_list ap; va_start(ap, str); vutf8printf(stdout, str, &ap); va_end(ap); if (m_colored) { ResetColor(true); } printf("\n"); } if (logfile && m_logFileLevel >= LOG_LVL_BASIC) { va_list ap; outTimestamp(logfile); va_start(ap, str); vfprintf(logfile, str, ap); fprintf(logfile, "\n"); va_end(ap); fflush(logfile); } fflush(stdout); } void Log::outDetail(const char* str, ...) { if (!str) { return; } if (m_logLevel >= LOG_LVL_DETAIL) { if (m_colored) { SetColor(true, m_colors[LogDetails]); } if (m_includeTime) { outTime(); } va_list ap; va_start(ap, str); vutf8printf(stdout, str, &ap); va_end(ap); if (m_colored) { ResetColor(true); } printf("\n"); } if (logfile && m_logFileLevel >= LOG_LVL_DETAIL) { outTimestamp(logfile); va_list ap; va_start(ap, str); vfprintf(logfile, str, ap); va_end(ap); fprintf(logfile, "\n"); fflush(logfile); } fflush(stdout); } void Log::outDebug(const char* str, ...) { if (!str) { return; } if (m_logLevel >= LOG_LVL_DEBUG) { if (m_colored) { SetColor(true, m_colors[LogDebug]); } if (m_includeTime) { outTime(); } va_list ap; va_start(ap, str); vutf8printf(stdout, str, &ap); va_end(ap); if (m_colored) { ResetColor(true); } printf("\n"); } if (logfile && m_logFileLevel >= LOG_LVL_DEBUG) { outTimestamp(logfile); va_list ap; va_start(ap, str); vfprintf(logfile, str, ap); va_end(ap); fprintf(logfile, "\n"); fflush(logfile); } fflush(stdout); } void Log::outCommand(uint32 account, const char* str, ...) { if (!str) { return; } if (m_logLevel >= LOG_LVL_DETAIL) { if (m_colored) { SetColor(true, m_colors[LogDetails]); } if (m_includeTime) { outTime(); } va_list ap; va_start(ap, str); vutf8printf(stdout, str, &ap); va_end(ap); if (m_colored) { ResetColor(true); } printf("\n"); } if (logfile && m_logFileLevel >= LOG_LVL_DETAIL) { va_list ap; outTimestamp(logfile); va_start(ap, str); vfprintf(logfile, str, ap); fprintf(logfile, "\n"); va_end(ap); fflush(logfile); } if (m_gmlog_per_account) { if (FILE* per_file = openGmlogPerAccount(account)) { va_list ap; outTimestamp(per_file); va_start(ap, str); vfprintf(per_file, str, ap); fprintf(per_file, "\n"); va_end(ap); fclose(per_file); } } else if (gmLogfile) { va_list ap; outTimestamp(gmLogfile); va_start(ap, str); vfprintf(gmLogfile, str, ap); fprintf(gmLogfile, "\n"); va_end(ap); fflush(gmLogfile); } fflush(stdout); } void Log::outWarden() { if (m_includeTime) { outTime(); } printf("\n"); if (wardenLogfile) { outTimestamp(wardenLogfile); fprintf(wardenLogfile, "\n"); fflush(wardenLogfile); } fflush(stdout); } void Log::outWarden(const char* str, ...) { if (!str) { return; } if (m_logLevel >= LOG_LVL_DETAIL) { if (m_colored) { SetColor(true, m_colors[LogNormal]); } if (m_includeTime) { outTime(); } va_list ap; va_start(ap, str); vutf8printf(stdout, str, &ap); va_end(ap); if (m_colored) { ResetColor(true); } printf("\n"); } if (wardenLogfile && m_logFileLevel >= LOG_LVL_DETAIL) { va_list ap; outTimestamp(wardenLogfile); fprintf(wardenLogfile, "[Warden]: "); va_start(ap, str); vfprintf(wardenLogfile, str, ap); fprintf(wardenLogfile, "\n"); va_end(ap); fflush(wardenLogfile); } fflush(stdout); } void Log::outChar(const char* str, ...) { if (!str) { return; } if (charLogfile) { va_list ap; outTimestamp(charLogfile); va_start(ap, str); vfprintf(charLogfile, str, ap); fprintf(charLogfile, "\n"); va_end(ap); fflush(charLogfile); } } void Log::outErrorScriptLib() { if (m_includeTime) { outTime(); } fprintf(stderr, "\n"); if (logfile) { outTimestamp(logfile); if (m_scriptLibName) { fprintf(logfile, "<%s ERROR:> ", m_scriptLibName); } else { fprintf(logfile, ": "); } fflush(logfile); } if (scriptErrLogFile) { outTimestamp(scriptErrLogFile); fprintf(scriptErrLogFile, "\n"); fflush(scriptErrLogFile); } fflush(stderr); } void Log::outErrorScriptLib(const char* err, ...) { if (!err) { return; } if (m_colored) { SetColor(false, m_colors[LogError]); } if (m_includeTime) { outTime(); } va_list ap; va_start(ap, err); vutf8printf(stderr, err, &ap); va_end(ap); if (m_colored) { ResetColor(false); } fprintf(stderr, "\n"); if (logfile) { outTimestamp(logfile); if (m_scriptLibName) { fprintf(logfile, "<%s ERROR>: ", m_scriptLibName); } else { fprintf(logfile, ": "); } va_start(ap, err); vfprintf(logfile, err, ap); va_end(ap); fprintf(logfile, "\n"); fflush(logfile); } if (scriptErrLogFile) { outTimestamp(scriptErrLogFile); va_list ap; va_start(ap, err); vfprintf(scriptErrLogFile, err, ap); va_end(ap); fprintf(scriptErrLogFile, "\n"); fflush(scriptErrLogFile); } fflush(stderr); } void Log::outWorldPacketDump(uint32 socket, uint32 opcode, char const* opcodeName, ByteBuffer const* packet, bool incoming) { if (!worldLogfile) { return; } ACE_GUARD(ACE_Thread_Mutex, GuardObj, m_worldLogMtx); outTimestamp(worldLogfile); fprintf(worldLogfile, "\n%s:\nSOCKET: %u\nLENGTH: %lu\nOPCODE: %s (0x%.4X)\nDATA:\n", incoming ? "CLIENT" : "SERVER", socket, packet->size(), opcodeName, opcode); size_t p = 0; while (p < packet->size()) { for (size_t j = 0; j < 16 && p < packet->size(); ++j) { fprintf(worldLogfile, "%.2X ", (*packet)[p++]); } fprintf(worldLogfile, "\n"); } fprintf(worldLogfile, "\n\n"); fflush(worldLogfile); } void Log::outCharDump(const char* str, uint32 account_id, uint32 guid, const char* name) { if (charLogfile) { fprintf(charLogfile, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n", account_id, guid, name, str); fflush(charLogfile); } } void Log::outRALog(const char* str, ...) { if (!str) { return; } if (raLogfile) { va_list ap; outTimestamp(raLogfile); va_start(ap, str); vfprintf(raLogfile, str, ap); fprintf(raLogfile, "\n"); va_end(ap); fflush(raLogfile); } fflush(stdout); } void Log::WaitBeforeContinueIfNeed() { int mode = sConfig.GetIntDefault("WaitAtStartupError", 0); if (mode < 0) { printf("\nPress for continue\n"); std::string line; std::getline(std::cin, line); } else if (mode > 0) { printf("\nWait %u secs for continue.\n", mode); BarGoLink bar(mode); for (int i = 0; i < mode; ++i) { bar.step(); ACE_OS::sleep(1); } } } void Log::setScriptLibraryErrorFile(char const* fname, char const* libName) { m_scriptLibName = libName; if (scriptErrLogFile) { fclose(scriptErrLogFile); } if (!fname) { scriptErrLogFile = NULL; return; } std::string fileName = m_logsDir; fileName.append(fname); scriptErrLogFile = fopen(fileName.c_str(), "a"); } void outstring_log(const char* str, ...) { if (!str) { return; } char buf[256]; va_list ap; va_start(ap, str); vsnprintf(buf, 256, str, ap); va_end(ap); sLog.outString("%s", buf); } void detail_log(const char* str, ...) { if (!str) { return; } char buf[256]; va_list ap; va_start(ap, str); vsnprintf(buf, 256, str, ap); va_end(ap); sLog.outDetail("%s", buf); } void debug_log(const char* str, ...) { if (!str) { return; } char buf[256]; va_list ap; va_start(ap, str); vsnprintf(buf, 256, str, ap); va_end(ap); DEBUG_LOG("%s", buf); } void error_log(const char* str, ...) { if (!str) { return; } char buf[256]; va_list ap; va_start(ap, str); vsnprintf(buf, 256, str, ap); va_end(ap); sLog.outError("%s", buf); } void error_db_log(const char* str, ...) { if (!str) { return; } char buf[256]; va_list ap; va_start(ap, str); vsnprintf(buf, 256, str, ap); va_end(ap); sLog.outErrorDb("%s", buf); } void setScriptLibraryErrorFile(char const* fname, char const* libName) { sLog.setScriptLibraryErrorFile(fname, libName); } void script_error_log(const char* str, ...) { if (!str) { return; } char buf[256]; va_list ap; va_start(ap, str); vsnprintf(buf, 256, str, ap); va_end(ap); sLog.outErrorScriptLib("%s", buf); }