diff --git a/worldeditadditions/lib/normalize_test.lua b/worldeditadditions/lib/normalize_test.lua index 9fa3a1e..99a167c 100644 --- a/worldeditadditions/lib/normalize_test.lua +++ b/worldeditadditions/lib/normalize_test.lua @@ -21,7 +21,9 @@ local metatable = { } metatable.__index = metatable -local normalize_test = function(test_name, def) +local registered_tests = {} + +local register_test = function(test_name, def) --- -- 1: Validation --- @@ -45,8 +47,22 @@ local normalize_test = function(test_name, def) -- 2: Normalisation --- setmetatable(def, metatable) - - return test_name, def + registered_tests[test_name] = def end -return normalize_test \ No newline at end of file +local normalize_test = {} +normalize_test.__index = normalize_test + +normalize_test.__call = function(self, test_name, def) + register_test(test_name, def) +end + +normalize_test.get_registered_tests = function() + local ret = {} + for k, v in pairs(registered_tests) do + ret[k] = v + end + return ret +end + +return setmetatable({}, normalize_test) \ No newline at end of file diff --git a/worldeditadditions_commands/commands/test/test.lua b/worldeditadditions_commands/commands/test/test.lua index 8d6f059..13092cc 100644 --- a/worldeditadditions_commands/commands/test/test.lua +++ b/worldeditadditions_commands/commands/test/test.lua @@ -10,7 +10,9 @@ local wea_cmd = worldeditadditions_commands local test_dir = wea_cmd.modpath .. "/commands/test/tests/" -- Load tests with init function -local tests = dofile(test_dir .. "init.lua")(test_dir) +dofile(test_dir .. "init.lua")(test_dir) +local tests = worldeditadditions.normalize_test.get_registered_tests() + -- Helper functions local set_colour = function(colour, text) return minetest.colorize(colour, text) diff --git a/worldeditadditions_commands/commands/test/tests/credits.test.lua b/worldeditadditions_commands/commands/test/tests/credits.test.lua index 618e9df..1b0f79d 100644 --- a/worldeditadditions_commands/commands/test/tests/credits.test.lua +++ b/worldeditadditions_commands/commands/test/tests/credits.test.lua @@ -12,7 +12,7 @@ local credits = { } local Notify = worldeditadditions_core.notify -return worldeditadditions.normalize_test("credits", { +worldeditadditions.normalize_test("credits", { params = "N\\A", description = "Sends WEA credits to player in info notification format.", func = function(name, params_table) diff --git a/worldeditadditions_commands/commands/test/tests/init.lua b/worldeditadditions_commands/commands/test/tests/init.lua index 7577afb..d2efccc 100644 --- a/worldeditadditions_commands/commands/test/tests/init.lua +++ b/worldeditadditions_commands/commands/test/tests/init.lua @@ -3,6 +3,7 @@ local test_id_paths = { "credits.test.lua", "notify.test.lua", "notify_bad.test.lua", + -- "notify_suppress.test.lua", -- "stacktrace.test.lua", } @@ -11,10 +12,7 @@ local update = function(a,k,v) a[k] = v end -- Test loader local test_loader = function (path) - local ret = {} - for _, v in ipairs(test_id_paths) do - update(ret, dofile(path .. v)) - end + for _, v in ipairs(test_id_paths) do dofile(path .. v) end return ret end diff --git a/worldeditadditions_commands/commands/test/tests/notify.test.lua b/worldeditadditions_commands/commands/test/tests/notify.test.lua index eca6ed1..b0d433d 100644 --- a/worldeditadditions_commands/commands/test/tests/notify.test.lua +++ b/worldeditadditions_commands/commands/test/tests/notify.test.lua @@ -1,5 +1,5 @@ local Notify = worldeditadditions_core.notify -return worldeditadditions.normalize_test("notify", { +worldeditadditions.normalize_test("notify", { params = "", description = "Sends message to player in all main notification formats (error, warn, ok, info).", func = function(name, params_table) diff --git a/worldeditadditions_commands/commands/test/tests/notify_bad.test.lua b/worldeditadditions_commands/commands/test/tests/notify_bad.test.lua index 16afeb6..8e9c374 100644 --- a/worldeditadditions_commands/commands/test/tests/notify_bad.test.lua +++ b/worldeditadditions_commands/commands/test/tests/notify_bad.test.lua @@ -1,5 +1,5 @@ local Notify = worldeditadditions_core.notify -return worldeditadditions.normalize_test("notifybad", { +worldeditadditions.normalize_test("notifybad", { params = "N/A", description = "Sends badly formed messages to player to test error handling.", func = function(name, params_table) diff --git a/worldeditadditions_commands/commands/test/tests/notify_suppress.test.lua b/worldeditadditions_commands/commands/test/tests/notify_suppress.test.lua new file mode 100644 index 0000000..e69de29 diff --git a/worldeditadditions_core/utils/notify/notify.lua b/worldeditadditions_core/utils/notify/notify.lua index 994c652..ab18c9c 100644 --- a/worldeditadditions_core/utils/notify/notify.lua +++ b/worldeditadditions_core/utils/notify/notify.lua @@ -10,6 +10,7 @@ local globalstate = { -- Remember to connect Notify.get_player_suppressed in -- ..\worldeditadditions_commands\player_notify_suppress.lua suppressed_players = {}, + -- Mostly for testing, may make get() and set() for this in future on_error_send_all = false, } @@ -22,6 +23,8 @@ local Notify = {} -- Local send handler local send = function(name, ntype, message, colour, message_coloured) + -- Check if notifications are suppressed for the player + if globalstate.suppressed_players[name] then return false end -- Do validation local sucess, details = validate.all(name, message, colour) -- Report errors if any @@ -55,13 +58,13 @@ local send = function(name, ntype, message, colour, message_coloured) return true end ---- Send a notification of type `ntype`. +--- Send a notification of type `ntype` (for metatable). -- (Same as `Notify[ntype](name, message)`) -- @param string name The name of the player to send the notification to. -- @param string ntype The type of notification. -- @param string message The message to send. -- @return table The Notify instance. -function Notify.__call(name, ntype, message) +local call = function(name, ntype, message) if ntype ~= "__call" and not Notify[ntype] then Notify.error(name, "Invalid notification type: " .. ntype) Notify.error(name, "Message: " .. message) @@ -71,20 +74,18 @@ function Notify.__call(name, ntype, message) return true end +setmetatable(Notify, {__call = call}) + --- Send a custom notification. --- @param string name The name of the player to send the notification to. --- @param string ntype The type of notification. --- @param string message The message to send. --- @param string colour optional): The colour of the notification. --- @param message_coloured boolean? Optional. Whether the message should be coloured. +-- @param string name The name of the player to send the notification to. +-- @param string ntype The type of notification. +-- @param string message The message to send. +-- @param string? colour Optional. The colour of the notification. +-- @param boolean? message_coloured Optional. Whether the message should be coloured. -- @return boolean True if all parameters are valid, false otherwise. -- @example Predefined notification types --- Notify.error(name, message) --- Notify.errinfo(name, message) -- For verbose errors and stack traces --- Notify.warn(name, message) --- Notify.wrninfo(name, message) -- For verbose warnings and stack traces --- Notify.ok(name, message) --- Notify.info(name, message) +-- Notify.custom(name, "custom", "This one is magenta!", "#FF00FF", true) +-- Notify.custom(name, "custom", "This one is gold with white text!", "#FFC700") function Notify.custom(name, ntype, message, colour, message_coloured) if not colour then colour = "#FFFFFF" end return send(name, ntype, message, colour, message_coloured) @@ -92,6 +93,13 @@ end --- Register the aforementioned predefined notification types. +-- @param string name The name of the player to send the notification to. +-- @param string message The message to send. +-- @example +-- Notify.error(name, "multi-line error!\n" .. debug.traceback()) +-- Notify.warn(name, "This is the last coloured message type!") +-- Notify.ok(name, "I am ok!") +-- Notify.info(name, "There once was a ship that put to sea...") do local type_colours = { error = {"#FF5555", true}, @@ -106,4 +114,51 @@ do end end +--- Local suppression status handler +-- @param string name The name of the player to check. +-- @param table suppress The table of suppressed players. +-- @return boolean True if the player is not suppressed or +-- if the player is clear(ed), false otherwise. +local check_clear_suppressed = function(name, suppress) + if suppress[name] then + if type(suppress[name]) == "function" then return false end + if suppress[name].cancel then + suppress[name]:cancel() + else suppress[name] = nil end + end + return true +end + +--- Suppress a player's notifications. +-- @param string name The name of the player to suppress. +-- @param number > 1 time The number of seconds to suppress notifications for. +-- number < 1 immediately removes the suppression. +function Notify.suppress_for_player(name, time) + local suppress = globalstate.suppress + -- If the player is already suppressed, cancel it unless it's a function + if not check_clear_suppressed(name, suppress) then return false end + if time < 1 then return end + if not minetest.after then -- Just being paranoid again + Notify.warn(name, "minetest.after does not exist. THIS SHOULD NOT HAPPEN.") + Notify.warn(name, "Notifications will not be suppressed. Please open an issue!") + else suppress[name] = minetest.after(time, Notify.suppress_for_player, name, -1) end +end + +--- Suppress a player's notifications while function executes. +function Notify.suppress_for_function(name, func) + local suppress = globalstate.suppress + -- If the player is already suppressed, cancel it unless it's a function + if not check_clear_suppressed(name, suppress) then return false end + suppress[name] = func + suppress[name]() + suppress[name] = nil +end + +--- WorldEdit compatibility +-- if worldedit and type(worldedit.player_notify) == "function" then +-- worldedit.player_notify = function(name, message, ntype) +-- Notify(name, ntype, message) +-- end +-- end + return Notify \ No newline at end of file