+class ILogOutput;
+
+enum LogLevel {
+ LL_NONE, // Special level that is always printed
+ LL_ERROR,
+ LL_WARNING,
+ LL_ACTION, // In-game actions
+ LL_INFO,
+ LL_VERBOSE,
+ LL_MAX,
+};
+
+enum LogColor {
+ LOG_COLOR_NEVER,
+ LOG_COLOR_ALWAYS,
+ LOG_COLOR_AUTO,
+};
+
+typedef u8 LogLevelMask;
+#define LOGLEVEL_TO_MASKLEVEL(x) (1 << x)
+
+class Logger {
+public:
+ void addOutput(ILogOutput *out);
+ void addOutput(ILogOutput *out, LogLevel lev);
+ void addOutputMasked(ILogOutput *out, LogLevelMask mask);
+ void addOutputMaxLevel(ILogOutput *out, LogLevel lev);
+ LogLevelMask removeOutput(ILogOutput *out);
+ void setLevelSilenced(LogLevel lev, bool silenced);
+
+ void registerThread(const std::string &name);
+ void deregisterThread();
+
+ void log(LogLevel lev, const std::string &text);
+ // Logs without a prefix
+ void logRaw(LogLevel lev, const std::string &text);
+
+ void setTraceEnabled(bool enable) { m_trace_enabled = enable; }
+ bool getTraceEnabled() { return m_trace_enabled; }
+
+ static LogLevel stringToLevel(const std::string &name);
+ static const std::string getLevelLabel(LogLevel lev);
+
+ static LogColor color_mode;
+
+private:
+ void logToOutputsRaw(LogLevel, const std::string &line);
+ void logToOutputs(LogLevel, const std::string &combined,
+ const std::string &time, const std::string &thread_name,
+ const std::string &payload_text);
+
+ const std::string getThreadName();
+
+ std::vector<ILogOutput *> m_outputs[LL_MAX];
+
+ // Should implement atomic loads and stores (even though it's only
+ // written to when one thread has access currently).
+ // Works on all known architectures (x86, ARM, MIPS).
+ volatile bool m_silenced_levels[LL_MAX];
+ std::map<std::thread::id, std::string> m_thread_names;
+ mutable std::mutex m_mutex;
+ bool m_trace_enabled;
+};
+
+class ILogOutput {
+public:
+ virtual void logRaw(LogLevel, const std::string &line) = 0;
+ virtual void log(LogLevel, const std::string &combined,
+ const std::string &time, const std::string &thread_name,
+ const std::string &payload_text) = 0;
+};