From 4306035ef23c537f4cb2058273d4de7be63b42b4 Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Wed, 18 May 2022 02:31:08 +0100 Subject: [PATCH] core: implement safe_region --- worldeditadditions_core/core/run_command.lua | 8 ++- worldeditadditions_core/core/safe_region.lua | 65 ++++++++++++++++++++ 2 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 worldeditadditions_core/core/safe_region.lua diff --git a/worldeditadditions_core/core/run_command.lua b/worldeditadditions_core/core/run_command.lua index 4a1e252..22428fa 100644 --- a/worldeditadditions_core/core/run_command.lua +++ b/worldeditadditions_core/core/run_command.lua @@ -1,5 +1,7 @@ local we_c = worldeditadditions_core +-- WARNING: safe_region MUST NOT be imported more than once, as it defines chat commands. If you want to import it again elsewhere, check first that multiple dofile() calls don't execute a file more than once. +local safe_region = dofile(we_c.modpath.."/core/safe_region.lua") local human_size = dofile(we_c.modpath.."/core/lib/human_size.lua") -- TODO: Reimplement worldedit.player_notify(player_name, msg_text) @@ -39,9 +41,9 @@ local function run_command(cmdname, options, player_name, paramtext) if potential_changes > limit then worldedit.player_notify(player_name, "/"..cmdname.." "..paramtext.."' may affect up to "..human_size(potential_changes).." nodes. Type //y to continue, or //n to cancel (see the //saferegion command to control when this message appears).") - - -- TODO: Wrap run_command_stage2 in safe_region stuff - run_command_stage2(player_name, options.func, parse_result) + safe_region(player_name, cmdname, function() + run_command_stage2(player_name, options.func, parse_result) + end) end else run_command_stage2(player_name, options.func, parse_result) diff --git a/worldeditadditions_core/core/safe_region.lua b/worldeditadditions_core/core/safe_region.lua new file mode 100644 index 0000000..0facbf4 --- /dev/null +++ b/worldeditadditions_core/core/safe_region.lua @@ -0,0 +1,65 @@ + +-- ███████ █████ ███████ ███████ ██████ ███████ ██████ ██ ██████ ███ ██ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ +-- ███████ ███████ █████ █████ ██████ █████ ██ ███ ██ ██ ██ ██ ██ ██ +-- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +-- ███████ ██ ██ ██ ███████ ██ ██ ███████ ██████ ██ ██████ ██ ████ + +local worldedit_command_y, worldedit_command_n + +if minetest.global_exists("worldedit") then + worldedit_command_y = minetest.registered_commands["/y"].func + worldedit_command_n = minetest.registered_commands["/n"].func +end + +--- A table that holds at most 1 pending function call per player. +local pending_calls = {} + +--- Captures the given function in the safe_region subsystem for later execution. +-- @param player_name string The name of the player. +-- @param cmdname string The name of the command being executed. +-- @param func function The function to execute later. Will be passed NO ARGUMENTS should it ever get executed in the future (this is not guaranteed). +-- @returns nil +local function safe_region(player_name, cmdname, func) + pending_calls[player_name] = { + cmdname = cmdname, + func = func + } +end + +minetest.override_chatcommand("/y", { + params = "", + description = "Run a pending operation that was captured by the safe region system earlier.", + func = function(player_name) + if pending_calls[player_name] == nil then + if minetest.global_exists("worldedit") and worldedit_command_y ~= nil then + worldedit_command_y(player_name) + else + worldedit.player_notify(player_name, "There aren't any pending operations at the moment.") + end + else + pending_calls[player_name].func() + pending_calls[player_name] = nil + end + end +}) + +minetest.override_chatcommand("/n", { + params = "", + description = "Abort a pending operation that was captured by the safe region system.", + func = function(player_name) + if pending_calls[player_name] == nil then + if minetest.global_exists("worldedit") and worldedit_command_y ~= nil then + worldedit_command_n(player_name) + else + worldedit.player_notify(player_name, "There aren't any operations pending, so there's nothing to abort.") + end + else + worldedit.player_notify(player_name, "Aborting captured command /"..pending_calls[player_name].cmdname..".") + pending_calls[player_name] = nil + end + end +}) + + +return safe_region