--[[ ------------------------------------------------------------ -- DPHs debug logger ------------------------------------------------------------ -- You may distribute this together with your addon as long as you keep this header intact. -- Latest version available from: https://www.moddb.com/mods/stalker-anomaly/addons/dphs-debug-logger -- -- by dph-hcl ------------------------------------------------------------ ]]-- LOG_LEVEL_INFO = 1 LOG_LEVEL_WARNING = 2 LOG_LEVEL_ERROR = 3 log_levels = { [LOG_LEVEL_INFO] = "INFO", [LOG_LEVEL_WARNING] = "WARNING", [LOG_LEVEL_ERROR] = "ERROR" } local default_cfg = { ["file"] = "dph.log", ["targets"] = { ["log"] = 1, ["gamelog"] = 2, ["pda"] = 3, } } function new(cfg, mods) -- setup private properties local private = {} private.modules = {} private.enabled = false local public = {} public.config = default_cfg for k, v in pairs(cfg) do public.config[k] = v end private.targets = { ["log"] = function(mod, level, entry, ...) local ln = public.format_entry(mod, level, entry, ...) local file = io.open(public.config.file,"a+") if not file then printe(public.format_entry("dph_debug_log/log", LOG_LEVEL_ERROR, "Unable to open logfile %s! Entry logged on the following line.", public.config.file)) printf(public.format_entry(mod, level, entry, ...)) end file:write(ln .. "\n") file:close() end, ["gamelog"] = function (mod, level, entry, ...) local ln = public.format_entry(mod, level, entry, ...) if level >= 3 then printe(ln) else printf(ln) end end, ["pda"] = function (mod, level, entry, ...) local ln = entry if (select('#',...) >= 1) then ln = string.format(entry, ...) end if (db) and (db.actor) then db.actor:give_game_news("[" .. log_levels[level] .. "] " .. mod, ln, "", 5000, 10000) else printe(public.format_entry("dph_debug_log/pda", LOG_LEVEL_ERROR, "Could not send message to PDA: Actor does not exist! Entry logged on the following line.")) printf(public.format_entry(mod, level, entry, ...)) end end, } private.compare_paths = function(pt, mt) m = tostring(mt) p = tostring(pt) if (not m) or (not p) then return false end local mm = str_explode(m, "/") local pp = str_explode(p, "/") for i, seg in ipairs(mm) do if (not pp[i]) or (seg ~= pp[i]) then return false end end return true end private.module_enabled = function(mod) for i, m in ipairs(private.modules) do if private.compare_paths(mod, m) then return true end end return false end private.log_entry = function(mod, level, entry, ...) if (private.enabled) and private.module_enabled(mod) then for t, l in pairs(public.config.targets) do if level >= l then public.log_to_target(t, mod, level, entry, ...) end end end end -- public interface public.enable = function() private.enabled = true public.info("dph_debug_log", "DPHs DEBUG LOGGER VERSION %s | Log instance started", public.version()) return private.enabled end public.disable = function() private.enabled = false return private.enabled end public.register_module = function(m) table.insert(private.modules, m) end public.unregister_module = function(mod) for i, m in ipairs(private.modules) do if mod == m then private.modules[i] = nil end end end public.define_target = function(name, log_function) private.targets[name] = log_function end public.log_to_target = function(target, mod, level, entry, ...) local status, err = pcall(private.targets[target], mod, level, entry, ...) if err then printe(public.format_entry("dph_debug_log", LOG_LEVEL_ERROR, "Target %s threw an exception while logging <%s> %s", target, mod, entry)) printe("ERROR: %s", err) printf(public.format_entry(mod, level, entry, ...)) end end public.format_entry = function(mod, level, entry, ...) local strf = entry if (select('#',...) >= 1) then strf = string.format(entry, ...) end local n1 = "[" .. log_levels[level] .. "]" .. string.rep(" ", 8 - #log_levels[level]) local n2 = "<" .. mod .. ">" .. string.rep(" ", 28 - #mod) return (n1 .. n2 .. strf) end public.info = function(mod, entry, ...) return private.log_entry(mod, LOG_LEVEL_INFO, entry, ...) end public.warn = function(mod, entry, ...) return private.log_entry(mod, LOG_LEVEL_WARNING, entry, ...) end public.error = function(mod, entry, ...) return private.log_entry(mod, LOG_LEVEL_ERROR, entry, ...) end public.pda = function(mod, entry, ...) return public.log_to_target("pda", mod, LOG_LEVEL_INFO, entry, ...) end public.log_table = function(mod, name, tbl) local ts = utils_data.print_table(tbl, false, true) public.info(mod, "TABLE %s \n%s", name, ts) end public.version = function() return 1 end -- constructor for i, m in ipairs(mods) do public.register_module(m) end public.register_module("dph_debug_log") return public end