Divergent/mods/Dynamic Zone Transitions/gamedata/scripts/dynamic_zone_debug.script

207 lines
7.8 KiB
Plaintext

--[[
DYNAMIC ZONE
Original Author(s)
Singustromo <singustromo at disroot.org>
Edited by
License
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
(https://creativecommons.org/licenses/by-nc-sa/4.0)
--]]
parent = _G["dynamic_zone"]
if not (parent and parent.VERSION and parent.VERSION >= 20241224) then return end
local opt = dynamic_zone_mcm
local utils = dynamic_zone_utils
------------------------------------------
-- Global Variables & Constants --
------------------------------------------
CONST_BLOCKSTATECHANGE_NOTIFY_DELAY_MS = 100
CONST_LOGGING_PREFIX = "[DZT]" -- used for console logging
valid_logging_channels = { def = "INFO", info = "INFO", warning = "WARNING", error = "ERROR" }
registered_logging_channels = { --[[
info = instance,
warning = instance,
...
--]] }
local log_mcm
---------------------
-- Callbacks --
---------------------
function on_game_start()
RegisterScriptCallback("on_game_load", inject_debug_commands)
RegisterScriptCallback("dynzone_changed_block_state", dynzone_changed_block_state)
-- Due to this, functors called before creating those instances will log to xray console
log_mcm = log_register("info", "Debug")
create_logging_instances()
end
function inject_debug_commands()
-- no need, if not enabled. Idk if it would even break something
if not (DEV_DEBUG or DEV_DEBUG_DEV) then return end
local CMD = debug_cmd_list.command_get_list()
function CMD.dynamic_zone(_, __, x)
x:SendOutput("/ DYNAMIC ZONE " .. parent.VERSION_STRING)
parent.main_routine{ force = true }
end
function CMD.dynamic_zone_accessible(_, __, x)
x:SendOutput("- Reset all route states!")
parent.addon_safe_removal()
end
ui_debug_launcher.inject("action", { name = "[DYNZONE] Trigger",
cmd = "dynamic_zone", hide_ui = 2, key = "DIK_D" } )
ui_debug_launcher.inject("action", { name = "[DYNZONE] Clear routes",
cmd = "dynamic_zone_accessible", hide_ui = 2 } )
end
-- Just informs us about the exact block state
-- A bit hacky to prevent recursive referencing
function dynzone_changed_block_state(previous, current)
if (not opt.get("verbose")) then
UnregisterScriptCallback("dynzone_changed_block_state", dynzone_changed_block_state)
end
-- We only use it in this function, to prevent recursive referencing
local route_manager = dynamic_zone_routes
-- Done this way, so it shows the updated values changed by other functions
utils.timed_call(CONST_BLOCKSTATECHANGE_NOTIFY_DELAY_MS, function(previous, current)
local output_str = "Previously Blocked routes:"
for route_id, _ in pairs(previous) do
output_str = output_str .. "\n" .. route_manager.route_tostring(route_id, true)
end
if (size_table(previous) > 0) then
log_mcm("%s\nA total of %s routes were blocked.",
output_str, size_table(previous))
end
local output_str = "Newly Blocked routes:"
for route_id, _ in pairs(current) do
output_str = output_str .. "\n" .. route_manager.route_tostring(route_id, true)
end
if (size_table(current) > 0) then
log_mcm("%s\nA total of %s routes are freshly blocked.",
output_str, size_table(current))
end
local blocked, discovered = 0, 0
for route_id, route in route_manager.iterate_routes(true) do
blocked = (route.blocked) and (blocked +1) or blocked
discovered = (route.block_discovered) and (discovered +1) or discovered
end
log_mcm("A total of %s routes are blocked (%s discovered)", blocked, discovered)
return true
end, previous, current)
end
---------------------------
-- Debugging --
---------------------------
-- These are mainly used by this script or others where it is more suited than mcm logging
function log(message, ...)
if (not opt.get("verbose")) then return end
local args = {...}
local output = string.format("%s %s", CONST_LOGGING_PREFIX, message)
printf(output, unpack(args))
end
-- These two are more important, thus are always logged to console.
function log_warn(message, ...)
local args = {...}
local output = string.format("~%s %s", CONST_LOGGING_PREFIX, message)
printf(output, unpack(args))
end
function log_error(message, ...)
local args = {...}
local output = string.format("!%s %s", CONST_LOGGING_PREFIX, message)
printf(output, unpack(args))
end
-- REQUIRES MOD-CONFIGURATION-MENU (MCM)
-- We only create logging instances `on_game_start`, so we don't load mcm_log earlier than necessary.
function create_logging_instances()
if (_g.is_empty(registered_logging_channels)) then
return
elseif not (mcm_log and mcm_log.new) then
log_warn("MCM Logging utility not found. Falling back to console logging.")
return
end
for channelname, value in pairs(registered_logging_channels) do
if (type(value) == "userdata") then goto continue end
local logger = mcm_log and mcm_log.new and mcm_log.new(channelname)
if (not logger) then
log_warn("Unable to create a MCM logging instance! Falling back to console logging.")
callstack()
return
end
logger.continuous = true
logger.enabled = true
registered_logging_channels[channelname] = logger
:: continue ::
end
end
-- Called like this: e.g. log_info = debug.log_register("info", "Anomalies")
-- will only return function that prints to logs, when verbose setting is active
-- Will log via the MCM utility, only to console as fallback
-- Using string.format to be able to use same rules as ISO C sprintf
-- @param channelname logging level - defaults to info, if invalid
-- @param identifier optional
-- @returns pointer to logging function which uses mcm logging, when available
function log_register(channelname, identifier)
if (not channelname) then return end
identifier = identifier and string.upper(identifier)
channelname = valid_logging_channels[string.lower(channelname)]
or valid_logging_channels.def
registered_logging_channels[channelname] = true
local id_prefix = (identifier and type(identifier == "string"))
and (" - " .. identifier) or ""
return function(message, ...)
if (not opt.get("verbose")) then return end
local data = { channel = channelname, id = id_prefix }
local logger = (type(registered_logging_channels[data.channel]) ~= "boolean")
and registered_logging_channels[data.channel]
-- Fallback for e.g. before `on_game_start` or if `mcm_log` does not exist
if not (logger and logger.log) then
printf(string.format(CONST_LOGGING_PREFIX .. message, ...))
return
end
local default_prefix = logger.prefix
if (data.id and data.id ~= "") then
logger.prefix = logger.prefix .. data.id
end
logger:log(string.format(message, ...))
logger.prefix = default_prefix
end
end