From 12424c584fc61bd27f5a1be3e669eda836fea5e1 Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Wed, 16 Apr 2014 13:35:46 -0700 Subject: [PATCH 01/17] Initial pseudocode --- worldedit_protection/init.lua | 75 +++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 worldedit_protection/init.lua diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua new file mode 100644 index 0000000..1b55633 --- /dev/null +++ b/worldedit_protection/init.lua @@ -0,0 +1,75 @@ +--I am assuming it's creative mode. What should I do in survival? + +--if there's no protection mod, no worldedit means no editing, worldedit means editing anywhere (old behaviour) +--if there's a protection mod, no worldedit means editing only in your area, worldedit means editing in no-man's land too, areas means editing anywhere. + +--let the other mod load first +minetest.after(0, function() + --I would use mod.soft_depend from commonlib, but there are multiple mods that could create owned land + PROTECTION_MOD_EXISTS = minetest.is_protected == old_is_protected + --else fall back to old behaviour, where + --worldedit privilege is permission to edit everything +end) + +--this is privs= within chatcommands that actually change land +--(should be the same functions as safe_region) +function worldedit.get_privs() + if not PROTECTION_MOD_EXISTS then + --no protection mod, worldedit means editing anywhere + return {worldedit=true} + end + --protection mod, can edit inside your area without worldedit privilege + --(worldedit and areas let you edit in no-man's land and other-owned area) + return {worldedit=false} -- this array could also be empty +end + +function worldedit.can_edit_volume(name) + --old you-can-worldedit-everything behaviour + if not PROTECTION_MOD_EXISTS then + --then if you were able to run this command, then you have the worldedit privilege. + return true + end + --new ownership-based behaviour + + --You can set areas, so you can worldedit them too. + if minetest.check_player_privs(name, {areas=true}) then + return true + end + + --all-or-nothing here + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + --pos1, pos2 = worldedit.sort_pos(pos1, pos2) --does this matter? + for i in area:iterp(pos1, pos2) do + + --THIS SECTION IGNORES the distinction of area that is owned by someone else, but still editable + --this is treated as area owned by the editor, or no-man's land depending on if it's shared with one person or everyone + -- + --If it was treated differently (it's not), then single edits would not be able to cross the border between someone else's editable land, and no-man's land, to prevent accidental writes. It may cross the border between multiple people's editable land (or should it?), such as to create a bridge between two skyscrapers that were previously built separately. + -- + --This needs testing for the other changes first. + + --Is it owned? + if minetest.is_protected(i) then + --Is it someone else's? + if minetest.is_protected(i, name) then + --already checked the ability to make it mine (areas) + minetest.chat_send_player(name, "Someone else owns at least part of what you want to edit") + return false + end + --it's mine + --continue + + --no-man's land + --can I edit that? + elseif not minetest.check_player_privs(name, {worldedit=true}) then --cache this check? + minetest.chat_send_player(name, "You can only edit area in which you own a plot (missing worldedit privilege)") + return false + end + end + + --the whole thing is + --a) owned by me, + --b) owned by no one and I have the worldedit privilege, and/or + --c) owned by someone else and I have the areas privilege. + return true +end From f2436db108c32dd493e8ab671b14d47fe54d43ec Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Wed, 16 Apr 2014 14:01:40 -0700 Subject: [PATCH 02/17] Use old behaviour when not in creative mode. --- worldedit_protection/init.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index 1b55633..702b89c 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -1,5 +1,3 @@ ---I am assuming it's creative mode. What should I do in survival? - --if there's no protection mod, no worldedit means no editing, worldedit means editing anywhere (old behaviour) --if there's a protection mod, no worldedit means editing only in your area, worldedit means editing in no-man's land too, areas means editing anywhere. @@ -14,8 +12,9 @@ end) --this is privs= within chatcommands that actually change land --(should be the same functions as safe_region) function worldedit.get_privs() - if not PROTECTION_MOD_EXISTS then - --no protection mod, worldedit means editing anywhere + if not PROTECTION_MOD_EXISTS or not minetest.setting_getbool("creative_mode") then + --no protection mod, or not the kind of world where people can just create nodes out of thin air, + --worldedit privilege means editing anywhere return {worldedit=true} end --protection mod, can edit inside your area without worldedit privilege From ae5a7376c0eb88d000f61a3d1bda8afe72512cb9 Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Wed, 16 Apr 2014 18:54:16 -0700 Subject: [PATCH 03/17] Require the "server" privilege for commands that write to files (but not for reads) Inconsistently require the "worldedit" privilege, based on creative mode and the existence of a land ownership mod. --- worldedit_commands/init.lua | 84 +++++++++++++++++------------------ worldedit_protection/init.lua | 8 ++-- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index 2bbfeed..ad2b7fc 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -82,7 +82,7 @@ minetest.register_chatcommand("/about", { minetest.register_chatcommand("/inspect", { params = "on/off/1/0/true/false/yes/no/enable/disable/", description = "Enable or disable node inspection", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) if param == "on" or param == "1" or param == "true" or param == "yes" or param == "enable" or param == "" then worldedit.inspect[name] = true @@ -115,7 +115,7 @@ end) minetest.register_chatcommand("/reset", { params = "", description = "Reset the region so that it is empty", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) worldedit.pos1[name] = nil worldedit.pos2[name] = nil @@ -129,7 +129,7 @@ minetest.register_chatcommand("/reset", { minetest.register_chatcommand("/mark", { params = "", description = "Show markers at the region positions", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) worldedit.mark_pos1(name) worldedit.mark_pos2(name) @@ -140,7 +140,7 @@ minetest.register_chatcommand("/mark", { minetest.register_chatcommand("/unmark", { params = "", description = "Hide markers if currently shown", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] worldedit.pos1[name] = nil @@ -156,7 +156,7 @@ minetest.register_chatcommand("/unmark", { minetest.register_chatcommand("/pos1", { params = "", description = "Set WorldEdit region position 1 to the player's location", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) local pos = minetest.get_player_by_name(name):getpos() pos.x, pos.y, pos.z = math.floor(pos.x + 0.5), math.floor(pos.y + 0.5), math.floor(pos.z + 0.5) @@ -169,7 +169,7 @@ minetest.register_chatcommand("/pos1", { minetest.register_chatcommand("/pos2", { params = "", description = "Set WorldEdit region position 2 to the player's location", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) local pos = minetest.get_player_by_name(name):getpos() pos.x, pos.y, pos.z = math.floor(pos.x + 0.5), math.floor(pos.y + 0.5), math.floor(pos.z + 0.5) @@ -182,7 +182,7 @@ minetest.register_chatcommand("/pos2", { minetest.register_chatcommand("/p", { params = "set/set1/set2/get", description = "Set WorldEdit region, WorldEdit position 1, or WorldEdit position 2 by punching nodes, or display the current WorldEdit region", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) if param == "set" then --set both WorldEdit positions worldedit.set_pos[name] = "pos1" @@ -213,7 +213,7 @@ minetest.register_chatcommand("/p", { minetest.register_chatcommand("/fixedpos", { params = "set1/set2 x y z", description = "Set a WorldEdit region position to the position at (, , )", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) local found, _, flag, x, y, z = param:find("^(set[12])%s+([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)$") if found == nil then @@ -261,7 +261,7 @@ end) minetest.register_chatcommand("/volume", { params = "", description = "Display the volume of the current WorldEdit region", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] if pos1 == nil or pos2 == nil then @@ -287,7 +287,7 @@ end minetest.register_chatcommand("/set", { params = "", description = "Set the current WorldEdit region to ", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local node = get_node(name, param) @@ -318,7 +318,7 @@ end minetest.register_chatcommand("/replace", { params = " ", description = "Replace all instances of with in the current WorldEdit region", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") @@ -332,7 +332,7 @@ minetest.register_chatcommand("/replace", { minetest.register_chatcommand("/replaceinverse", { params = " ", description = "Replace all nodes other than with in the current WorldEdit region", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") @@ -361,7 +361,7 @@ end minetest.register_chatcommand("/hollowsphere", { params = " ", description = "Add hollow sphere centered at WorldEdit position 1 with radius , composed of ", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") @@ -374,7 +374,7 @@ minetest.register_chatcommand("/hollowsphere", { minetest.register_chatcommand("/sphere", { params = " ", description = "Add sphere centered at WorldEdit position 1 with radius , composed of ", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") @@ -402,7 +402,7 @@ end minetest.register_chatcommand("/hollowdome", { params = " ", description = "Add hollow dome centered at WorldEdit position 1 with radius , composed of ", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") @@ -415,7 +415,7 @@ minetest.register_chatcommand("/hollowdome", { minetest.register_chatcommand("/dome", { params = " ", description = "Add dome centered at WorldEdit position 1 with radius , composed of ", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") @@ -443,7 +443,7 @@ end minetest.register_chatcommand("/hollowcylinder", { params = "x/y/z/? ", description = "Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length and radius , composed of ", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$") @@ -461,7 +461,7 @@ minetest.register_chatcommand("/hollowcylinder", { minetest.register_chatcommand("/cylinder", { params = "x/y/z/? ", description = "Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length and radius , composed of ", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$") @@ -479,7 +479,7 @@ minetest.register_chatcommand("/cylinder", { minetest.register_chatcommand("/pyramid", { params = "x/y/z/? ", description = "Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height , composed of ", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos = get_position(name) local found, _, axis, height, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(.+)$") @@ -512,7 +512,7 @@ minetest.register_chatcommand("/pyramid", { minetest.register_chatcommand("/spiral", { params = " ", description = "Add spiral centered at WorldEdit position 1 with side length , height , space between walls , composed of ", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, length, height, space, nodename = param:find("^(%d+)%s+(%d+)%s+(%d+)%s+(.+)$") @@ -539,7 +539,7 @@ minetest.register_chatcommand("/spiral", { minetest.register_chatcommand("/copy", { params = "x/y/z/? ", description = "Copy the current WorldEdit region along the x/y/z/? axis by nodes", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$") @@ -565,7 +565,7 @@ minetest.register_chatcommand("/copy", { minetest.register_chatcommand("/move", { params = "x/y/z/? ", description = "Move the current WorldEdit region along the x/y/z/? axis by nodes", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$") @@ -592,7 +592,7 @@ minetest.register_chatcommand("/move", { minetest.register_chatcommand("/stack", { params = "x/y/z/? ", description = "Stack the current WorldEdit region along the x/y/z/? axis times", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis, repetitions = param:find("^([xyz%?])%s+([+-]?%d+)$") @@ -618,7 +618,7 @@ minetest.register_chatcommand("/stack", { minetest.register_chatcommand("/stretch", { params = " ", description = "Scale the current WorldEdit positions and region by a factor of , , along the X, Y, and Z axes, repectively, with position 1 as the origin", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, stretchx, stretchy, stretchz = param:find("^(%d+)%s+(%d+)%s+(%d+)$") @@ -652,7 +652,7 @@ minetest.register_chatcommand("/stretch", { minetest.register_chatcommand("/transpose", { params = "x/y/z/? x/y/z/?", description = "Transpose the current WorldEdit region along the x/y/z/? and x/y/z/? axes", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis1, axis2 = param:find("^([xyz%?])%s+([xyz%?])$") @@ -685,7 +685,7 @@ minetest.register_chatcommand("/transpose", { minetest.register_chatcommand("/flip", { params = "x/y/z/?", description = "Flip the current WorldEdit region along the x/y/z/? axis", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] if param == "?" then param = worldedit.player_axis(name) end @@ -704,7 +704,7 @@ minetest.register_chatcommand("/flip", { minetest.register_chatcommand("/rotate", { params = " ", description = "Rotate the current WorldEdit region around the axis by angle (90 degree increment)", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis, angle = param:find("^([xyz%?])%s+([+-]?%d+)$") @@ -736,7 +736,7 @@ minetest.register_chatcommand("/rotate", { minetest.register_chatcommand("/orient", { params = "", description = "Rotate oriented nodes in the current WorldEdit region around the Y axis by angle (90 degree increment)", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, angle = param:find("^([+-]?%d+)$") @@ -760,7 +760,7 @@ minetest.register_chatcommand("/orient", { minetest.register_chatcommand("/fixlight", { params = "", description = "Fix the lighting in the current WorldEdit region", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local count = worldedit.fixlight(pos1, pos2) @@ -771,7 +771,7 @@ minetest.register_chatcommand("/fixlight", { minetest.register_chatcommand("/hide", { params = "", description = "Hide all nodes in the current WorldEdit region non-destructively", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local count = worldedit.hide(pos1, pos2) @@ -782,7 +782,7 @@ minetest.register_chatcommand("/hide", { minetest.register_chatcommand("/suppress", { params = "", description = "Suppress all in the current WorldEdit region non-destructively", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local node = get_node(name, param) @@ -794,7 +794,7 @@ minetest.register_chatcommand("/suppress", { minetest.register_chatcommand("/highlight", { params = "", description = "Highlight in the current WorldEdit region by hiding everything else non-destructively", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local node = get_node(name, param) @@ -806,7 +806,7 @@ minetest.register_chatcommand("/highlight", { minetest.register_chatcommand("/restore", { params = "", description = "Restores nodes hidden with WorldEdit in the current WorldEdit region", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local count = worldedit.restore(pos1, pos2) @@ -817,7 +817,7 @@ minetest.register_chatcommand("/restore", { minetest.register_chatcommand("/save", { params = "", description = "Save the current WorldEdit region to \"(world folder)/schems/.we\"", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv(), server=true}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] if param == "" then @@ -851,7 +851,7 @@ minetest.register_chatcommand("/save", { minetest.register_chatcommand("/allocate", { params = "", description = "Set the region defined by nodes from \"(world folder)/schems/.we\" as the current WorldEdit region", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) local pos = get_position(name) if pos == nil then return end @@ -892,7 +892,7 @@ minetest.register_chatcommand("/allocate", { minetest.register_chatcommand("/load", { params = "", description = "Load nodes from \"(world folder)/schems/[.we[m]]\" with position 1 of the current WorldEdit region as the origin", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) local pos = get_position(name) if pos == nil then return end @@ -940,7 +940,7 @@ minetest.register_chatcommand("/load", { minetest.register_chatcommand("/lua", { params = "", description = "Executes as a Lua chunk in the global namespace", - privs = {worldedit=true, server=true}, + privs = {worldedit=worldedit.priv(), server=true}, func = function(name, param) local admin = minetest.setting_get("name") if not admin or not name == admin then @@ -959,7 +959,7 @@ minetest.register_chatcommand("/lua", { minetest.register_chatcommand("/luatransform", { params = "", description = "Executes as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region", - privs = {worldedit=true, server=true}, + privs = {worldedit=worldedit.priv(), server=true}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local admin = minetest.setting_get("name") @@ -980,7 +980,7 @@ minetest.register_chatcommand("/luatransform", { minetest.register_chatcommand("/mtschemcreate", { params = "", description = "Save the current WorldEdit region using the Minetest Schematic format to \"(world folder)/schems/.mts\"", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv(), server=true}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] if param == nil then @@ -1006,7 +1006,7 @@ minetest.register_chatcommand("/mtschemcreate", { minetest.register_chatcommand("/mtschemplace", { params = "", description = "Load nodes from \"(world folder)/schems/.mts\" with position 1 of the current WorldEdit region as the origin", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) if param == nil then worldedit.player_notify(name, "no filename specified") @@ -1029,7 +1029,7 @@ minetest.register_chatcommand("/mtschemplace", { minetest.register_chatcommand("/mtschemprob", { params = "start/finish/get", description = "Begins node probability entry for Minetest schematics, gets the nodes that have probabilities set, or ends node probability entry", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = function(name, param) if param == "start" then --start probability setting worldedit.set_pos[name] = "prob" @@ -1070,7 +1070,7 @@ minetest.register_on_player_receive_fields( minetest.register_chatcommand("/clearobjects", { params = "", description = "Clears all objects within the WorldEdit region", - privs = {worldedit=true}, + privs = {worldedit=worldedit.priv()}, func = safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local count = worldedit.clearobjects(pos1, pos2) diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index 702b89c..86bcb13 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -9,17 +9,17 @@ minetest.after(0, function() --worldedit privilege is permission to edit everything end) ---this is privs= within chatcommands that actually change land +--this is privs={worldedit=this()} within chatcommands that actually change land --(should be the same functions as safe_region) -function worldedit.get_privs() +function worldedit.priv() if not PROTECTION_MOD_EXISTS or not minetest.setting_getbool("creative_mode") then --no protection mod, or not the kind of world where people can just create nodes out of thin air, --worldedit privilege means editing anywhere - return {worldedit=true} + return true end --protection mod, can edit inside your area without worldedit privilege --(worldedit and areas let you edit in no-man's land and other-owned area) - return {worldedit=false} -- this array could also be empty + return false end function worldedit.can_edit_volume(name) From df159efcee699c914a68549709dcd38da88ad47b Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Thu, 17 Apr 2014 10:37:24 -0700 Subject: [PATCH 04/17] Check privs not just during registration of chatcommands Creative mode could change while the server is running. --- worldedit_commands/depends.txt | 3 +- worldedit_commands/init.lua | 252 ++++++++++++++++----------------- worldedit_protection/init.lua | 42 ++++-- 3 files changed, 155 insertions(+), 142 deletions(-) diff --git a/worldedit_commands/depends.txt b/worldedit_commands/depends.txt index df8caff..3bdd90c 100644 --- a/worldedit_commands/depends.txt +++ b/worldedit_commands/depends.txt @@ -1 +1,2 @@ -worldedit \ No newline at end of file +worldedit +worldedit_protection diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index ad2b7fc..233cbba 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -82,8 +82,8 @@ minetest.register_chatcommand("/about", { minetest.register_chatcommand("/inspect", { params = "on/off/1/0/true/false/yes/no/enable/disable/", description = "Enable or disable node inspection", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) if param == "on" or param == "1" or param == "true" or param == "yes" or param == "enable" or param == "" then worldedit.inspect[name] = true local axis, sign = worldedit.player_axis(name) @@ -95,7 +95,7 @@ minetest.register_chatcommand("/inspect", { else worldedit.player_notify(name, "invalid usage: " .. param) end - end, + end), }) minetest.register_on_punchnode(function(pos, node, puncher) @@ -115,33 +115,33 @@ end) minetest.register_chatcommand("/reset", { params = "", description = "Reset the region so that it is empty", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) worldedit.pos1[name] = nil worldedit.pos2[name] = nil worldedit.mark_pos1(name) worldedit.mark_pos2(name) worldedit.set_pos[name] = nil worldedit.player_notify(name, "region reset") - end, + end), }) minetest.register_chatcommand("/mark", { params = "", description = "Show markers at the region positions", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) worldedit.mark_pos1(name) worldedit.mark_pos2(name) worldedit.player_notify(name, "region marked") - end, + end), }) minetest.register_chatcommand("/unmark", { params = "", description = "Hide markers if currently shown", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] worldedit.pos1[name] = nil worldedit.pos2[name] = nil @@ -150,40 +150,40 @@ minetest.register_chatcommand("/unmark", { worldedit.pos1[name] = pos1 worldedit.pos2[name] = pos2 worldedit.player_notify(name, "region unmarked") - end, + end), }) minetest.register_chatcommand("/pos1", { params = "", description = "Set WorldEdit region position 1 to the player's location", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) local pos = minetest.get_player_by_name(name):getpos() pos.x, pos.y, pos.z = math.floor(pos.x + 0.5), math.floor(pos.y + 0.5), math.floor(pos.z + 0.5) worldedit.pos1[name] = pos worldedit.mark_pos1(name) worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos)) - end, + end), }) minetest.register_chatcommand("/pos2", { params = "", description = "Set WorldEdit region position 2 to the player's location", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) local pos = minetest.get_player_by_name(name):getpos() pos.x, pos.y, pos.z = math.floor(pos.x + 0.5), math.floor(pos.y + 0.5), math.floor(pos.z + 0.5) worldedit.pos2[name] = pos worldedit.mark_pos2(name) worldedit.player_notify(name, "position 2 set to " .. minetest.pos_to_string(pos)) - end, + end), }) minetest.register_chatcommand("/p", { params = "set/set1/set2/get", description = "Set WorldEdit region, WorldEdit position 1, or WorldEdit position 2 by punching nodes, or display the current WorldEdit region", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) if param == "set" then --set both WorldEdit positions worldedit.set_pos[name] = "pos1" worldedit.player_notify(name, "select positions by punching two nodes") @@ -207,14 +207,14 @@ minetest.register_chatcommand("/p", { else worldedit.player_notify(name, "unknown subcommand: " .. param) end - end, + end), }) minetest.register_chatcommand("/fixedpos", { params = "set1/set2 x y z", description = "Set a WorldEdit region position to the position at (, , )", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) local found, _, flag, x, y, z = param:find("^(set[12])%s+([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)$") if found == nil then worldedit.player_notify(name, "invalid usage: " .. param) @@ -230,7 +230,7 @@ minetest.register_chatcommand("/fixedpos", { worldedit.mark_pos2(name) worldedit.player_notify(name, "position 2 set to " .. minetest.pos_to_string(pos)) end - end, + end), }) minetest.register_on_punchnode(function(pos, node, puncher) @@ -261,8 +261,8 @@ end) minetest.register_chatcommand("/volume", { params = "", description = "Display the volume of the current WorldEdit region", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] if pos1 == nil or pos2 == nil then worldedit.player_notify(name, "no region selected") @@ -275,7 +275,7 @@ minetest.register_chatcommand("/volume", { .. abs(pos2.x - pos1.x) + 1 .. "*" .. abs(pos2.y - pos1.y) + 1 .. "*" .. abs(pos2.z - pos1.z) + 1 .. ")") - end, + end), }) local check_set = function(name, param) @@ -287,13 +287,13 @@ end minetest.register_chatcommand("/set", { params = "", description = "Set the current WorldEdit region to ", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local node = get_node(name, param) local count = worldedit.set(pos1, pos2, node) worldedit.player_notify(name, count .. " nodes set") - end, check_set), + end, check_set)), }) local check_replace = function(name, param) @@ -318,29 +318,29 @@ end minetest.register_chatcommand("/replace", { params = " ", description = "Replace all instances of with in the current WorldEdit region", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") local newsearchnode = worldedit.normalize_nodename(searchnode) local newreplacenode = worldedit.normalize_nodename(replacenode) local count = worldedit.replace(pos1, pos2, newsearchnode, newreplacenode) worldedit.player_notify(name, count .. " nodes replaced") - end, check_replace), + end, check_replace)), }) minetest.register_chatcommand("/replaceinverse", { params = " ", description = "Replace all nodes other than with in the current WorldEdit region", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") local newsearchnode = worldedit.normalize_nodename(searchnode) local newreplacenode = worldedit.normalize_nodename(replacenode) local count = worldedit.replaceinverse(pos1, pos2, searchnode, replacenode) worldedit.player_notify(name, count .. " nodes replaced") - end, check_replace), + end, check_replace)), }) local check_sphere = function(name, param) @@ -361,27 +361,27 @@ end minetest.register_chatcommand("/hollowsphere", { params = " ", description = "Add hollow sphere centered at WorldEdit position 1 with radius , composed of ", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") local node = get_node(name, nodename) local count = worldedit.hollow_sphere(pos, tonumber(radius), node) worldedit.player_notify(name, count .. " nodes added") - end, check_sphere), + end, check_sphere)), }) minetest.register_chatcommand("/sphere", { params = " ", description = "Add sphere centered at WorldEdit position 1 with radius , composed of ", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") local node = get_node(name, nodename) local count = worldedit.sphere(pos, tonumber(radius), node) worldedit.player_notify(name, count .. " nodes added") - end, check_sphere), + end, check_sphere)), }) local check_dome = function(name, param) @@ -402,27 +402,27 @@ end minetest.register_chatcommand("/hollowdome", { params = " ", description = "Add hollow dome centered at WorldEdit position 1 with radius , composed of ", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") local node = get_node(name, nodename) local count = worldedit.hollow_dome(pos, tonumber(radius), node) worldedit.player_notify(name, count .. " nodes added") - end, check_dome), + end, check_dome)), }) minetest.register_chatcommand("/dome", { params = " ", description = "Add dome centered at WorldEdit position 1 with radius , composed of ", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") local node = get_node(name, nodename) local count = worldedit.dome(pos, tonumber(radius), node) worldedit.player_notify(name, count .. " nodes added") - end, check_dome), + end, check_dome)), }) local check_cylinder = function(name, param) @@ -443,8 +443,8 @@ end minetest.register_chatcommand("/hollowcylinder", { params = "x/y/z/? ", description = "Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length and radius , composed of ", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$") length = tonumber(length) @@ -455,14 +455,14 @@ minetest.register_chatcommand("/hollowcylinder", { local node = get_node(name, nodename) local count = worldedit.hollow_cylinder(pos, axis, length, tonumber(radius), node) worldedit.player_notify(name, count .. " nodes added") - end, check_cylinder), + end, check_cylinder)), }) minetest.register_chatcommand("/cylinder", { params = "x/y/z/? ", description = "Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length and radius , composed of ", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$") length = tonumber(length) @@ -473,14 +473,14 @@ minetest.register_chatcommand("/cylinder", { local node = get_node(name, nodename) local count = worldedit.cylinder(pos, axis, length, tonumber(radius), node) worldedit.player_notify(name, count .. " nodes added") - end, check_cylinder), + end, check_cylinder)), }) minetest.register_chatcommand("/pyramid", { params = "x/y/z/? ", description = "Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height , composed of ", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos = get_position(name) local found, _, axis, height, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(.+)$") height = tonumber(height) @@ -506,14 +506,14 @@ minetest.register_chatcommand("/pyramid", { if not node then return nil end height = tonumber(height) return math.ceil(((height * 2 + 1) ^ 2) * height / 3) - end), + end)), }) minetest.register_chatcommand("/spiral", { params = " ", description = "Add spiral centered at WorldEdit position 1 with side length , height , space between walls , composed of ", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, length, height, space, nodename = param:find("^(%d+)%s+(%d+)%s+(%d+)%s+(.+)$") local node = get_node(name, nodename) @@ -533,14 +533,14 @@ minetest.register_chatcommand("/spiral", { local node = get_node(name, nodename) if not node then return nil end return check_region(name, param) - end), + end)), }) minetest.register_chatcommand("/copy", { params = "x/y/z/? ", description = "Copy the current WorldEdit region along the x/y/z/? axis by nodes", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$") if found == nil then @@ -559,14 +559,14 @@ minetest.register_chatcommand("/copy", { function(name, param) local volume = check_region(name, param) return volume and volume * 2 or volume - end), + end)), }) minetest.register_chatcommand("/move", { params = "x/y/z/? ", description = "Move the current WorldEdit region along the x/y/z/? axis by nodes", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$") if found == nil then @@ -586,14 +586,14 @@ minetest.register_chatcommand("/move", { worldedit.mark_pos1(name) worldedit.mark_pos2(name) worldedit.player_notify(name, count .. " nodes moved") - end, check_region), + end, check_region)), }) minetest.register_chatcommand("/stack", { params = "x/y/z/? ", description = "Stack the current WorldEdit region along the x/y/z/? axis times", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis, repetitions = param:find("^([xyz%?])%s+([+-]?%d+)$") repetitions = tonumber(repetitions) @@ -612,14 +612,14 @@ minetest.register_chatcommand("/stack", { local count = check_region(name, param) if count then return (tonumber(repetitions) + 1) * count end return nil - end), + end)), }) minetest.register_chatcommand("/stretch", { params = " ", description = "Scale the current WorldEdit positions and region by a factor of , , along the X, Y, and Z axes, repectively, with position 1 as the origin", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, stretchx, stretchy, stretchz = param:find("^(%d+)%s+(%d+)%s+(%d+)$") stretchx, stretchy, stretchz = tonumber(stretchx), tonumber(stretchy), tonumber(stretchz) @@ -646,14 +646,14 @@ minetest.register_chatcommand("/stretch", { local count = check_region(name, param) if count then return tonumber(stretchx) * tonumber(stretchy) * tonumber(stretchz) * count end return nil - end), + end)), }) minetest.register_chatcommand("/transpose", { params = "x/y/z/? x/y/z/?", description = "Transpose the current WorldEdit region along the x/y/z/? and x/y/z/? axes", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis1, axis2 = param:find("^([xyz%?])%s+([xyz%?])$") if axis1 == "?" then axis1 = worldedit.player_axis(name) end @@ -679,14 +679,14 @@ minetest.register_chatcommand("/transpose", { return nil end return check_region(name, param) - end), + end)), }) minetest.register_chatcommand("/flip", { params = "x/y/z/?", description = "Flip the current WorldEdit region along the x/y/z/? axis", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] if param == "?" then param = worldedit.player_axis(name) end local count = worldedit.flip(pos1, pos2, param) @@ -698,14 +698,14 @@ minetest.register_chatcommand("/flip", { return nil end return check_region(name, param) - end), + end)), }) minetest.register_chatcommand("/rotate", { params = " ", description = "Rotate the current WorldEdit region around the axis by angle (90 degree increment)", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis, angle = param:find("^([xyz%?])%s+([+-]?%d+)$") if axis == "?" then axis = worldedit.player_axis(name) end @@ -730,14 +730,14 @@ minetest.register_chatcommand("/rotate", { return nil end return check_region(name, param) - end), + end)), }) minetest.register_chatcommand("/orient", { params = "", description = "Rotate oriented nodes in the current WorldEdit region around the Y axis by angle (90 degree increment)", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, angle = param:find("^([+-]?%d+)$") local count = worldedit.orient(pos1, pos2, angle) @@ -754,71 +754,71 @@ minetest.register_chatcommand("/orient", { return nil end return check_region(name, param) - end), + end)), }) minetest.register_chatcommand("/fixlight", { params = "", description = "Fix the lighting in the current WorldEdit region", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local count = worldedit.fixlight(pos1, pos2) worldedit.player_notify(name, count .. " nodes updated") - end), + end)), }) minetest.register_chatcommand("/hide", { params = "", description = "Hide all nodes in the current WorldEdit region non-destructively", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local count = worldedit.hide(pos1, pos2) worldedit.player_notify(name, count .. " nodes hidden") - end), + end)), }) minetest.register_chatcommand("/suppress", { params = "", description = "Suppress all in the current WorldEdit region non-destructively", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local node = get_node(name, param) local count = worldedit.suppress(pos1, pos2, node) worldedit.player_notify(name, count .. " nodes suppressed") - end, check_set), + end, check_set)), }) minetest.register_chatcommand("/highlight", { params = "", description = "Highlight in the current WorldEdit region by hiding everything else non-destructively", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local node = get_node(name, param) local count = worldedit.highlight(pos1, pos2, node) worldedit.player_notify(name, count .. " nodes highlighted") - end, check_set), + end, check_set)), }) minetest.register_chatcommand("/restore", { params = "", description = "Restores nodes hidden with WorldEdit in the current WorldEdit region", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local count = worldedit.restore(pos1, pos2) worldedit.player_notify(name, count .. " nodes restored") - end), + end)), }) minetest.register_chatcommand("/save", { params = "", description = "Save the current WorldEdit region to \"(world folder)/schems/.we\"", - privs = {worldedit=worldedit.priv(), server=true}, - func = safe_region(function(name, param) + privs = {server=true}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] if param == "" then worldedit.player_notify(name, "invalid usage: " .. param) @@ -845,14 +845,14 @@ minetest.register_chatcommand("/save", { file:close() worldedit.player_notify(name, count .. " nodes saved") - end), + end)), }) minetest.register_chatcommand("/allocate", { params = "", description = "Set the region defined by nodes from \"(world folder)/schems/.we\" as the current WorldEdit region", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) local pos = get_position(name) if pos == nil then return end @@ -886,14 +886,14 @@ minetest.register_chatcommand("/allocate", { worldedit.mark_pos2(name) worldedit.player_notify(name, count .. " nodes allocated") - end, + end), }) minetest.register_chatcommand("/load", { params = "", description = "Load nodes from \"(world folder)/schems/[.we[m]]\" with position 1 of the current WorldEdit region as the origin", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) local pos = get_position(name) if pos == nil then return end @@ -934,14 +934,14 @@ minetest.register_chatcommand("/load", { local count = worldedit.deserialize(pos, value) worldedit.player_notify(name, count .. " nodes loaded") - end, + end), }) minetest.register_chatcommand("/lua", { params = "", description = "Executes as a Lua chunk in the global namespace", - privs = {worldedit=worldedit.priv(), server=true}, - func = function(name, param) + privs = {server=true}, + func = worldedit.privs(function(name, param) local admin = minetest.setting_get("name") if not admin or not name == admin then worldedit.player_notify(name, "this command can only be run by the server administrator") @@ -953,14 +953,14 @@ minetest.register_chatcommand("/lua", { else worldedit.player_notify(name, "code successfully executed", false) end - end, + end), }) minetest.register_chatcommand("/luatransform", { params = "", description = "Executes as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region", - privs = {worldedit=worldedit.priv(), server=true}, - func = safe_region(function(name, param) + privs = {server=true}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local admin = minetest.setting_get("name") if not admin or not name == admin then @@ -974,14 +974,14 @@ minetest.register_chatcommand("/luatransform", { else worldedit.player_notify(name, "code successfully executed", false) end - end), + end)), }) minetest.register_chatcommand("/mtschemcreate", { params = "", description = "Save the current WorldEdit region using the Minetest Schematic format to \"(world folder)/schems/.mts\"", - privs = {worldedit=worldedit.priv(), server=true}, - func = safe_region(function(name, param) + privs = {server=true}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] if param == nil then worldedit.player_notify(name, "No filename specified") @@ -1000,14 +1000,14 @@ minetest.register_chatcommand("/mtschemcreate", { worldedit.player_notify(name, "saved Minetest schematic to " .. param, false) end worldedit.prob_list[name] = {} - end), + end)), }) minetest.register_chatcommand("/mtschemplace", { params = "", description = "Load nodes from \"(world folder)/schems/.mts\" with position 1 of the current WorldEdit region as the origin", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) if param == nil then worldedit.player_notify(name, "no filename specified") return @@ -1023,14 +1023,14 @@ minetest.register_chatcommand("/mtschemplace", { worldedit.player_notify(name, "placed Minetest schematic " .. param .. " at " .. minetest.pos_to_string(pos), false) end - end, + end), }) minetest.register_chatcommand("/mtschemprob", { params = "start/finish/get", description = "Begins node probability entry for Minetest schematics, gets the nodes that have probabilities set, or ends node probability entry", - privs = {worldedit=worldedit.priv()}, - func = function(name, param) + privs = {}, + func = worldedit.privs(function(name, param) if param == "start" then --start probability setting worldedit.set_pos[name] = "prob" worldedit.prob_list[name] = {} @@ -1053,7 +1053,7 @@ minetest.register_chatcommand("/mtschemprob", { else worldedit.player_notify(name, "unknown subcommand: " .. param) end - end, + end), }) minetest.register_on_player_receive_fields( @@ -1070,10 +1070,10 @@ minetest.register_on_player_receive_fields( minetest.register_chatcommand("/clearobjects", { params = "", description = "Clears all objects within the WorldEdit region", - privs = {worldedit=worldedit.priv()}, - func = safe_region(function(name, param) + privs = {}, + func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local count = worldedit.clearobjects(pos1, pos2) worldedit.player_notify(name, count .. " objects cleared") - end), + end)), }) diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index 86bcb13..cb9eb62 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -9,20 +9,30 @@ minetest.after(0, function() --worldedit privilege is permission to edit everything end) ---this is privs={worldedit=this()} within chatcommands that actually change land ---(should be the same functions as safe_region) -function worldedit.priv() - if not PROTECTION_MOD_EXISTS or not minetest.setting_getbool("creative_mode") then +--I wanted this function to directly choose the privileges for the chat command, but it only applies once. +--privs={worldedit=true [, server=true]} +--privs={worldedit=worldedit.priv() [, server=true]} +--instead, I had to wrap the rest of func = . +function worldedit.privs(func) + if not minetest.setting_getbool("creative_mode") or not PROTECTION_MOD_EXISTS then --no protection mod, or not the kind of world where people can just create nodes out of thin air, --worldedit privilege means editing anywhere - return true + if minetest.check_player_privs(name, {worldedit=true}) then + func(name, param) + else + return + end + else + --protection mod, can edit inside your area without worldedit privilege + --(worldedit and areas let you edit in no-man's land and other-owned area) + func(name, param) end - --protection mod, can edit inside your area without worldedit privilege - --(worldedit and areas let you edit in no-man's land and other-owned area) - return false end -function worldedit.can_edit_volume(name) +--this is... within chatcommands that actually change land +--(should be the same functions as safe_region) +--also check for permission when region is set? +function worldedit.can_edit_volume(name, pos1, pos2) --old you-can-worldedit-everything behaviour if not PROTECTION_MOD_EXISTS then --then if you were able to run this command, then you have the worldedit privilege. @@ -35,18 +45,20 @@ function worldedit.can_edit_volume(name) return true end + --[[I need to use a special per-command region (think /stack, or even worse, /move), the same one safe_region uses, but corner points instead of count... instead of a for loop interpolating between pos1 and pos2]]-- + --all-or-nothing here local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] --pos1, pos2 = worldedit.sort_pos(pos1, pos2) --does this matter? for i in area:iterp(pos1, pos2) do +--[[ + THIS SECTION IGNORES the distinction of area that is owned by someone else, but still editable + this is treated as area owned by the editor, or no-man's land depending on if it's shared with one person or everyone - --THIS SECTION IGNORES the distinction of area that is owned by someone else, but still editable - --this is treated as area owned by the editor, or no-man's land depending on if it's shared with one person or everyone - -- - --If it was treated differently (it's not), then single edits would not be able to cross the border between someone else's editable land, and no-man's land, to prevent accidental writes. It may cross the border between multiple people's editable land (or should it?), such as to create a bridge between two skyscrapers that were previously built separately. - -- - --This needs testing for the other changes first. + If it was treated differently (it's not), then single edits would not be able to cross the border between someone else's editable land, and no-man's land, to prevent accidental writes. It may cross the border between multiple people's editable land (or should it?), such as to create a bridge between two skyscrapers that were previously built separately. + This needs testing for the other changes first. +--]] --Is it owned? if minetest.is_protected(i) then --Is it someone else's? From 1d71e602b860d273b3c4f20febc4c0c3970cc6e9 Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Thu, 17 Apr 2014 10:45:24 -0700 Subject: [PATCH 05/17] add a second depend --- worldedit_protection/depends.txt | 1 + worldedit_protection/init.lua | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 worldedit_protection/depends.txt diff --git a/worldedit_protection/depends.txt b/worldedit_protection/depends.txt new file mode 100644 index 0000000..74054c6 --- /dev/null +++ b/worldedit_protection/depends.txt @@ -0,0 +1 @@ +worldedit diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index cb9eb62..19cf0a2 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -13,7 +13,7 @@ end) --privs={worldedit=true [, server=true]} --privs={worldedit=worldedit.priv() [, server=true]} --instead, I had to wrap the rest of func = . -function worldedit.privs(func) +worldedit.privs = function(func) if not minetest.setting_getbool("creative_mode") or not PROTECTION_MOD_EXISTS then --no protection mod, or not the kind of world where people can just create nodes out of thin air, --worldedit privilege means editing anywhere @@ -32,7 +32,7 @@ end --this is... within chatcommands that actually change land --(should be the same functions as safe_region) --also check for permission when region is set? -function worldedit.can_edit_volume(name, pos1, pos2) +worldedit.can_edit_volume = function(name, pos1, pos2) --old you-can-worldedit-everything behaviour if not PROTECTION_MOD_EXISTS then --then if you were able to run this command, then you have the worldedit privilege. From 7083a26e72b59b5db565e4de3d64e509064b2f0b Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Thu, 17 Apr 2014 12:35:15 -0700 Subject: [PATCH 06/17] Second function wrapper --- worldedit_protection/init.lua | 36 +++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index 19cf0a2..9ac9482 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -14,18 +14,22 @@ end) --privs={worldedit=worldedit.priv() [, server=true]} --instead, I had to wrap the rest of func = . worldedit.privs = function(func) - if not minetest.setting_getbool("creative_mode") or not PROTECTION_MOD_EXISTS then - --no protection mod, or not the kind of world where people can just create nodes out of thin air, - --worldedit privilege means editing anywhere - if minetest.check_player_privs(name, {worldedit=true}) then - func(name, param) + --this silly syntax was copied from safe_region, which is actually executed on chatcommand registration, and must return a function instead of the result of a function. + --The innermost anonymous function is declared. Then safe_region executes, adding a function wrapper around that function. Then worldedit.privs gets that as an argument, and adds another wrapper. The doubly-wrapped function is the one registered as a chatcommand. + return function(name, param) + if not minetest.setting_getbool("creative_mode") or not PROTECTION_MOD_EXISTS then + --no protection mod, or not the kind of world where people can just create nodes out of thin air, + --worldedit privilege means editing anywhere + if minetest.check_player_privs(name, {worldedit=true}) then + func(name, param) + else + return + end else - return + --protection mod, can edit inside your area without worldedit privilege + --(worldedit and areas let you edit in no-man's land and other-owned area) + func(name, param) end - else - --protection mod, can edit inside your area without worldedit privilege - --(worldedit and areas let you edit in no-man's land and other-owned area) - func(name, param) end end @@ -33,18 +37,14 @@ end --(should be the same functions as safe_region) --also check for permission when region is set? worldedit.can_edit_volume = function(name, pos1, pos2) - --old you-can-worldedit-everything behaviour - if not PROTECTION_MOD_EXISTS then - --then if you were able to run this command, then you have the worldedit privilege. + --old you-can-worldedit-everything behaviour. + if not PROTECTION_MOD_EXISTS or minetest.check_player_privs(name, {areas=true}) then + --If there's no mod, worldedit.privs already required that you have the worldedit privilege,then if you were able to run this command, then you have the worldedit privilege. + --Or, you can set areas, so you are allowed to worldedit them too. The ability to set the whole world as owned by yourself is already potentially destructive, what's more destructive capability? return true end --new ownership-based behaviour - --You can set areas, so you can worldedit them too. - if minetest.check_player_privs(name, {areas=true}) then - return true - end - --[[I need to use a special per-command region (think /stack, or even worse, /move), the same one safe_region uses, but corner points instead of count... instead of a for loop interpolating between pos1 and pos2]]-- --all-or-nothing here From 4475909a97d9c803fcdfabe3d46a04008784ce86 Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Fri, 18 Apr 2014 13:06:55 -0700 Subject: [PATCH 07/17] Disable node inspection on use if it was enabled before the worldedit privilege was removed from a player to prevent spamming. --- worldedit_commands/init.lua | 1 + worldedit_protection/init.lua | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index 233cbba..d6a5e05 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -107,6 +107,7 @@ minetest.register_on_punchnode(function(pos, node, puncher) node.name, minetest.pos_to_string(pos), node.param1, node.param2, name, axis .. (sign > 0 and "+" or "-")) else message = "inspector: worldedit privileges required" + worldedit.inspect[name] = nil end worldedit.player_notify(name, message) end diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index 9ac9482..4ee2ea3 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -35,8 +35,9 @@ end --this is... within chatcommands that actually change land --(should be the same functions as safe_region) ---also check for permission when region is set? -worldedit.can_edit_volume = function(name, pos1, pos2) +--also check for permission when region is set? no, //stack goes outside the boundaries. +--so the region is defined per-command on exec. +worldedit.can_edit_volume = function(name, pos1, pos2) --, func? --old you-can-worldedit-everything behaviour. if not PROTECTION_MOD_EXISTS or minetest.check_player_privs(name, {areas=true}) then --If there's no mod, worldedit.privs already required that you have the worldedit privilege,then if you were able to run this command, then you have the worldedit privilege. @@ -48,8 +49,8 @@ worldedit.can_edit_volume = function(name, pos1, pos2) --[[I need to use a special per-command region (think /stack, or even worse, /move), the same one safe_region uses, but corner points instead of count... instead of a for loop interpolating between pos1 and pos2]]-- --all-or-nothing here - local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - --pos1, pos2 = worldedit.sort_pos(pos1, pos2) --does this matter? + --local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + pos1, pos2 = worldedit.sort_pos(pos1, pos2) --does this matter? for i in area:iterp(pos1, pos2) do --[[ THIS SECTION IGNORES the distinction of area that is owned by someone else, but still editable @@ -81,6 +82,6 @@ worldedit.can_edit_volume = function(name, pos1, pos2) --the whole thing is --a) owned by me, --b) owned by no one and I have the worldedit privilege, and/or - --c) owned by someone else and I have the areas privilege. + --c) I have the areas privilege and it's possibly owned by someone else. return true end From 4b80eb82cccbd4f3aaa3dfc202998bd13ffad51b Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Fri, 18 Apr 2014 13:23:13 -0700 Subject: [PATCH 08/17] Allow using worldedit.privs() in an if statement or with a function argument. --- worldedit_commands/init.lua | 2 +- worldedit_protection/init.lua | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index d6a5e05..884bb16 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -101,7 +101,7 @@ minetest.register_chatcommand("/inspect", { minetest.register_on_punchnode(function(pos, node, puncher) local name = puncher:get_player_name() if worldedit.inspect[name] then - if minetest.check_player_privs(name, {worldedit=true}) then + if worldedit.privs() then local axis, sign = worldedit.player_axis(name) message = string.format("inspector: %s at %s (param1=%d, param2=%d) punched by %s facing the %s axis", node.name, minetest.pos_to_string(pos), node.param1, node.param2, name, axis .. (sign > 0 and "+" or "-")) diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index 4ee2ea3..2cefc50 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -9,11 +9,27 @@ minetest.after(0, function() --worldedit privilege is permission to edit everything end) +--[[ +Usage: + In chatcommand: + privs = {} + func = worldedit.privs(function(name, param)...end) + + In if statement: + name = minetest.get_player_name(node) + if worldedit.privs() then +--]] --I wanted this function to directly choose the privileges for the chat command, but it only applies once. --privs={worldedit=true [, server=true]} --privs={worldedit=worldedit.priv() [, server=true]} --instead, I had to wrap the rest of func = . worldedit.privs = function(func) + --This runs a function for a chatcommand's func = , + --or it can be used directly in an if statement. + if func == nil then + func = function(name, param) end + end + --this silly syntax was copied from safe_region, which is actually executed on chatcommand registration, and must return a function instead of the result of a function. --The innermost anonymous function is declared. Then safe_region executes, adding a function wrapper around that function. Then worldedit.privs gets that as an argument, and adds another wrapper. The doubly-wrapped function is the one registered as a chatcommand. return function(name, param) @@ -22,13 +38,15 @@ worldedit.privs = function(func) --worldedit privilege means editing anywhere if minetest.check_player_privs(name, {worldedit=true}) then func(name, param) + return true else - return + return false end else --protection mod, can edit inside your area without worldedit privilege --(worldedit and areas let you edit in no-man's land and other-owned area) func(name, param) + return true end end end From 88e4c635aa51bca0321a303b904722700a9bd6c5 Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Fri, 18 Apr 2014 16:52:34 -0700 Subject: [PATCH 09/17] Run worldedit.privs inside and outside of worldedit.can_edit_volume Never run worldedit.can_edit_volume without worldedit.privs surrounding it --- worldedit_commands/init.lua | 8 +++-- worldedit_protection/init.lua | 61 ++++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index 884bb16..1901ebb 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -291,9 +291,11 @@ minetest.register_chatcommand("/set", { privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - local node = get_node(name, param) - local count = worldedit.set(pos1, pos2, node) - worldedit.player_notify(name, count .. " nodes set") + if worldedit.can_edit_volume(area:iterp(pos1, pos2)) then + local node = get_node(name, param) + local count = worldedit.set(pos1, pos2, node) + worldedit.player_notify(name, count .. " nodes set") + end end, check_set)), }) diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index 2cefc50..4f28821 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -1,5 +1,5 @@ --if there's no protection mod, no worldedit means no editing, worldedit means editing anywhere (old behaviour) ---if there's a protection mod, no worldedit means editing only in your area, worldedit means editing in no-man's land too, areas means editing anywhere. +--if there's a protection mod (and it's creative mode), no worldedit means editing only in your area, worldedit means editing in no-man's land too, and areas means editing anywhere. --let the other mod load first minetest.after(0, function() @@ -10,6 +10,7 @@ minetest.after(0, function() end) --[[ +worldedit.privs replaces privs = {worldedit = true}, and also helps bypass volume permission checks. Usage: In chatcommand: privs = {} @@ -18,12 +19,17 @@ Usage: In if statement: name = minetest.get_player_name(node) if worldedit.privs() then + +Returns: + nil ( false) for no permission to worldedit anywhere, + 1 ( true ) for permission to worldedit at least somewhere, and + 2 (extra true ) for worldediting everywhere without checking for further permission. --]] --I wanted this function to directly choose the privileges for the chat command, but it only applies once. --privs={worldedit=true [, server=true]} --privs={worldedit=worldedit.priv() [, server=true]} --instead, I had to wrap the rest of func = . -worldedit.privs = function(func) +worldedit.privs = function(--[[name, ]]func--[[, param]]) --This runs a function for a chatcommand's func = , --or it can be used directly in an if statement. if func == nil then @@ -33,20 +39,26 @@ worldedit.privs = function(func) --this silly syntax was copied from safe_region, which is actually executed on chatcommand registration, and must return a function instead of the result of a function. --The innermost anonymous function is declared. Then safe_region executes, adding a function wrapper around that function. Then worldedit.privs gets that as an argument, and adds another wrapper. The doubly-wrapped function is the one registered as a chatcommand. return function(name, param) - if not minetest.setting_getbool("creative_mode") or not PROTECTION_MOD_EXISTS then + if minetest.check_player_privs(name, {areas=true}) then + --You can set areas, so you are allowed to worldedit them too. + --The ability to set the whole world as owned by yourself is already potentially destructive, what's more destructive capability? + func(name, param) + return 2 --edit everywhere without checks + elseif not minetest.setting_getbool("creative_mode") or not PROTECTION_MOD_EXISTS then --no protection mod, or not the kind of world where people can just create nodes out of thin air, --worldedit privilege means editing anywhere if minetest.check_player_privs(name, {worldedit=true}) then func(name, param) - return true + return 2 --edit everywhere without checks else - return false + --func(name, param) placeholder + return nil --edit nowhere end else --protection mod, can edit inside your area without worldedit privilege --(worldedit and areas let you edit in no-man's land and other-owned area) func(name, param) - return true + return 1 --edit at least somewhere, with checks end end end @@ -55,21 +67,35 @@ end --(should be the same functions as safe_region) --also check for permission when region is set? no, //stack goes outside the boundaries. --so the region is defined per-command on exec. -worldedit.can_edit_volume = function(name, pos1, pos2) --, func? - --old you-can-worldedit-everything behaviour. - if not PROTECTION_MOD_EXISTS or minetest.check_player_privs(name, {areas=true}) then - --If there's no mod, worldedit.privs already required that you have the worldedit privilege,then if you were able to run this command, then you have the worldedit privilege. - --Or, you can set areas, so you are allowed to worldedit them too. The ability to set the whole world as owned by yourself is already potentially destructive, what's more destructive capability? +--//move has disconnected sections, so it's passed as a list of points. +--which are deduplicated. +worldedit.can_edit_volume = function(--[[name, ]]volume, func--[[, param]]) + --volume is before func, unlike safe_region having func before count + --because func may be removed to have can_edit_volume in an if statement + --like worldedit.privs can be + if func == nil then + func = function(name, param) end + end + + --worldedit.privs was run once to prevent safe_region large area warnings, + --then safe_region was run to prevent unnecessary large-scale permission checks + --then can_edit_volume is run before //set to honor areas + --then worldedit.privs is run again to attempt skipping checks (resusing the same code) + --then set is finally run. + + --worldedit.privs said that 'name' can use worldedit at least somewhere + -- return value 1 (or 2) before this function was run. + + --Try skipping volume permission checks. + if worldedit.privs() == 2 then + func(name, param) return true end - --new ownership-based behaviour --[[I need to use a special per-command region (think /stack, or even worse, /move), the same one safe_region uses, but corner points instead of count... instead of a for loop interpolating between pos1 and pos2]]-- - --all-or-nothing here - --local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - pos1, pos2 = worldedit.sort_pos(pos1, pos2) --does this matter? - for i in area:iterp(pos1, pos2) do + --all or nothing here + for i in volume do --[[ THIS SECTION IGNORES the distinction of area that is owned by someone else, but still editable this is treated as area owned by the editor, or no-man's land depending on if it's shared with one person or everyone @@ -84,6 +110,7 @@ worldedit.can_edit_volume = function(name, pos1, pos2) --, func? if minetest.is_protected(i, name) then --already checked the ability to make it mine (areas) minetest.chat_send_player(name, "Someone else owns at least part of what you want to edit") + --func(name, param) placeholder return false end --it's mine @@ -93,6 +120,7 @@ worldedit.can_edit_volume = function(name, pos1, pos2) --, func? --can I edit that? elseif not minetest.check_player_privs(name, {worldedit=true}) then --cache this check? minetest.chat_send_player(name, "You can only edit area in which you own a plot (missing worldedit privilege)") + --func(name, param) placeholder return false end end @@ -101,5 +129,6 @@ worldedit.can_edit_volume = function(name, pos1, pos2) --, func? --a) owned by me, --b) owned by no one and I have the worldedit privilege, and/or --c) I have the areas privilege and it's possibly owned by someone else. + func(name, param) return true end From 098051d25e02b0db8457760680c6f7fa8493883f Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Fri, 18 Apr 2014 17:02:36 -0700 Subject: [PATCH 10/17] Respond correctly if .can_edit_volume is called outside of .privs I can't think of why that would happen. --- worldedit_protection/init.lua | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index 4f28821..9bb8c04 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -87,9 +87,16 @@ worldedit.can_edit_volume = function(--[[name, ]]volume, func--[[, param]]) -- return value 1 (or 2) before this function was run. --Try skipping volume permission checks. - if worldedit.privs() == 2 then + local wp = worldedit.privs() + if wp == 2 then func(name, param) return true + elseif wp == nil then + --safety feature in case worldedit.can_edit_volume is ever run alone, without being surrounded by worldedit.privs() + --Shouldn't ever get here. + --Any volume-changing function is surrounded by this, then safe_region, then worldedit.privs() + --func(name, param) placeholder + return false end --[[I need to use a special per-command region (think /stack, or even worse, /move), the same one safe_region uses, but corner points instead of count... instead of a for loop interpolating between pos1 and pos2]]-- @@ -126,9 +133,9 @@ worldedit.can_edit_volume = function(--[[name, ]]volume, func--[[, param]]) end --the whole thing is - --a) owned by me, - --b) owned by no one and I have the worldedit privilege, and/or - --c) I have the areas privilege and it's possibly owned by someone else. + --a) owned by me, and/or + --b) owned by no one and I have the worldedit privilege. + --c) I have the areas privilege and it's possibly owned by someone else. (returned earlier) func(name, param) return true end From bde3281508d023ca2fd4d437da855433819ccd3e Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Fri, 18 Apr 2014 18:21:08 -0700 Subject: [PATCH 11/17] copy .privs with .can_edit_volume for a function wrapper as well as a conditional for good measure. --- worldedit_commands/init.lua | 2 +- worldedit_protection/init.lua | 122 +++++++++++++++++----------------- 2 files changed, 63 insertions(+), 61 deletions(-) diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index 1901ebb..0aaa1d7 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -291,7 +291,7 @@ minetest.register_chatcommand("/set", { privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - if worldedit.can_edit_volume(area:iterp(pos1, pos2)) then + if worldedit.can_edit_volume(VoxelArea:iterp(pos1, pos2)) then local node = get_node(name, param) local count = worldedit.set(pos1, pos2, node) worldedit.player_notify(name, count .. " nodes set") diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index 9bb8c04..44632cd 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -29,11 +29,11 @@ Returns: --privs={worldedit=true [, server=true]} --privs={worldedit=worldedit.priv() [, server=true]} --instead, I had to wrap the rest of func = . -worldedit.privs = function(--[[name, ]]func--[[, param]]) +worldedit.privs = function(--[[name, ]]privsfunc--[[, param]]) --This runs a function for a chatcommand's func = , --or it can be used directly in an if statement. - if func == nil then - func = function(name, param) end + if privsfunc == nil then + privsfunc = function(name, param) end end --this silly syntax was copied from safe_region, which is actually executed on chatcommand registration, and must return a function instead of the result of a function. @@ -42,13 +42,13 @@ worldedit.privs = function(--[[name, ]]func--[[, param]]) if minetest.check_player_privs(name, {areas=true}) then --You can set areas, so you are allowed to worldedit them too. --The ability to set the whole world as owned by yourself is already potentially destructive, what's more destructive capability? - func(name, param) + privsfunc(name, param) return 2 --edit everywhere without checks elseif not minetest.setting_getbool("creative_mode") or not PROTECTION_MOD_EXISTS then --no protection mod, or not the kind of world where people can just create nodes out of thin air, --worldedit privilege means editing anywhere if minetest.check_player_privs(name, {worldedit=true}) then - func(name, param) + privsfunc(name, param) return 2 --edit everywhere without checks else --func(name, param) placeholder @@ -57,7 +57,7 @@ worldedit.privs = function(--[[name, ]]func--[[, param]]) else --protection mod, can edit inside your area without worldedit privilege --(worldedit and areas let you edit in no-man's land and other-owned area) - func(name, param) + privsfunc(name, param) return 1 --edit at least somewhere, with checks end end @@ -69,12 +69,12 @@ end --so the region is defined per-command on exec. --//move has disconnected sections, so it's passed as a list of points. --which are deduplicated. -worldedit.can_edit_volume = function(--[[name, ]]volume, func--[[, param]]) +worldedit.can_edit_volume = function(--[[name, ]]volume, volfunc--[[, param]]) --volume is before func, unlike safe_region having func before count --because func may be removed to have can_edit_volume in an if statement --like worldedit.privs can be - if func == nil then - func = function(name, param) end + if volfunc == nil then + volfunc = function(name, param) end end --worldedit.privs was run once to prevent safe_region large area warnings, @@ -83,59 +83,61 @@ worldedit.can_edit_volume = function(--[[name, ]]volume, func--[[, param]]) --then worldedit.privs is run again to attempt skipping checks (resusing the same code) --then set is finally run. - --worldedit.privs said that 'name' can use worldedit at least somewhere - -- return value 1 (or 2) before this function was run. + return function(name, param) + --worldedit.privs said that 'name' can use worldedit at least somewhere + -- return value 1 (or 2) before this function was run. - --Try skipping volume permission checks. - local wp = worldedit.privs() - if wp == 2 then - func(name, param) - return true - elseif wp == nil then - --safety feature in case worldedit.can_edit_volume is ever run alone, without being surrounded by worldedit.privs() - --Shouldn't ever get here. - --Any volume-changing function is surrounded by this, then safe_region, then worldedit.privs() - --func(name, param) placeholder - return false - end - - --[[I need to use a special per-command region (think /stack, or even worse, /move), the same one safe_region uses, but corner points instead of count... instead of a for loop interpolating between pos1 and pos2]]-- - - --all or nothing here - for i in volume do ---[[ - THIS SECTION IGNORES the distinction of area that is owned by someone else, but still editable - this is treated as area owned by the editor, or no-man's land depending on if it's shared with one person or everyone - - If it was treated differently (it's not), then single edits would not be able to cross the border between someone else's editable land, and no-man's land, to prevent accidental writes. It may cross the border between multiple people's editable land (or should it?), such as to create a bridge between two skyscrapers that were previously built separately. - - This needs testing for the other changes first. ---]] - --Is it owned? - if minetest.is_protected(i) then - --Is it someone else's? - if minetest.is_protected(i, name) then - --already checked the ability to make it mine (areas) - minetest.chat_send_player(name, "Someone else owns at least part of what you want to edit") - --func(name, param) placeholder - return false - end - --it's mine - --continue - - --no-man's land - --can I edit that? - elseif not minetest.check_player_privs(name, {worldedit=true}) then --cache this check? - minetest.chat_send_player(name, "You can only edit area in which you own a plot (missing worldedit privilege)") - --func(name, param) placeholder + --Try skipping volume permission checks. + local wp = worldedit.privs() + if wp == 2 then + volfunc(name, param) + return true + elseif wp == nil then + --safety feature in case worldedit.can_edit_volume is ever run alone, without being surrounded by worldedit.privs() + --Shouldn't ever get here. + --Any volume-changing function is surrounded by this, then safe_region, then worldedit.privs() + --volfunc(name, param) placeholder return false end - end - --the whole thing is - --a) owned by me, and/or - --b) owned by no one and I have the worldedit privilege. - --c) I have the areas privilege and it's possibly owned by someone else. (returned earlier) - func(name, param) - return true + --[[I need to use a special per-command region (think /stack, or even worse, /move), the same one safe_region uses, but corner points instead of count... instead of a for loop interpolating between pos1 and pos2]]-- + + --all or nothing here + for i in volume do + --[[ + THIS SECTION IGNORES the distinction of area that is owned by someone else, but still editable + this is treated as area owned by the editor, or no-man's land depending on if it's shared with one person or everyone + + If it was treated differently (it's not), then single edits would not be able to cross the border between someone else's editable land, and no-man's land, to prevent accidental writes. It may cross the border between multiple people's editable land (or should it?), such as to create a bridge between two skyscrapers that were previously built separately. + + This needs testing for the other changes first. + --]] + --Is it owned? + if minetest.is_protected(i) then + --Is it someone else's? + if minetest.is_protected(i, name) then + --already checked the ability to make it mine (areas) + minetest.chat_send_player(name, "Someone else owns at least part of what you want to edit") + --volfunc(name, param) placeholder + return false + end + --it's mine + --continue + + --no-man's land + --can I edit that? + elseif not minetest.check_player_privs(name, {worldedit=true}) then --cache this check? + minetest.chat_send_player(name, "You can only edit area in which you own a plot (missing worldedit privilege)") + --volfunc(name, param) placeholder + return false + end + end + + --the whole thing is + --a) owned by me, and/or + --b) owned by no one and I have the worldedit privilege. + --c) I have the areas privilege and it's possibly owned by someone else. (returned earlier) + volfunc(name, param) + return true + end end From 11647fca93ce65b3bfb4b86b899906429e106389 Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Fri, 18 Apr 2014 18:30:26 -0700 Subject: [PATCH 12/17] preemtive optimization - caching a per-node player permission check before the function actually works --- worldedit_protection/init.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index 44632cd..201775a 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -102,6 +102,9 @@ worldedit.can_edit_volume = function(--[[name, ]]volume, volfunc--[[, param]]) --[[I need to use a special per-command region (think /stack, or even worse, /move), the same one safe_region uses, but corner points instead of count... instead of a for loop interpolating between pos1 and pos2]]-- + --cache the result of this function for later + local has_worldedit = minetest.check_player_privs(name, {worldedit=true}) + --all or nothing here for i in volume do --[[ @@ -112,6 +115,7 @@ worldedit.can_edit_volume = function(--[[name, ]]volume, volfunc--[[, param]]) This needs testing for the other changes first. --]] + --Is it owned? if minetest.is_protected(i) then --Is it someone else's? @@ -126,7 +130,7 @@ worldedit.can_edit_volume = function(--[[name, ]]volume, volfunc--[[, param]]) --no-man's land --can I edit that? - elseif not minetest.check_player_privs(name, {worldedit=true}) then --cache this check? + elseif not has_worldedit then --use cached check minetest.chat_send_player(name, "You can only edit area in which you own a plot (missing worldedit privilege)") --volfunc(name, param) placeholder return false From c473fbb6c1146050d25bee5923a0e2a9ca313384 Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Sat, 19 Apr 2014 17:15:25 -0700 Subject: [PATCH 13/17] //set appears to respect area ownership hard depend on commonlib to soft depend on areas --- worldedit_commands/init.lua | 2 +- worldedit_protection/depends.txt | 1 + worldedit_protection/init.lua | 69 ++++++++++++++++++++++---------- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index 0aaa1d7..c128dfb 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -291,7 +291,7 @@ minetest.register_chatcommand("/set", { privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - if worldedit.can_edit_volume(VoxelArea:iterp(pos1, pos2)) then + if worldedit.can_edit_volume(name, {pos1, pos2}) then local node = get_node(name, param) local count = worldedit.set(pos1, pos2, node) worldedit.player_notify(name, count .. " nodes set") diff --git a/worldedit_protection/depends.txt b/worldedit_protection/depends.txt index 74054c6..f14783c 100644 --- a/worldedit_protection/depends.txt +++ b/worldedit_protection/depends.txt @@ -1 +1,2 @@ worldedit +commonlib diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index 201775a..fb8fcc2 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -1,13 +1,22 @@ --if there's no protection mod, no worldedit means no editing, worldedit means editing anywhere (old behaviour) --if there's a protection mod (and it's creative mode), no worldedit means editing only in your area, worldedit means editing in no-man's land too, and areas means editing anywhere. +--[[ --let the other mod load first minetest.after(0, function() --I would use mod.soft_depend from commonlib, but there are multiple mods that could create owned land - PROTECTION_MOD_EXISTS = minetest.is_protected == old_is_protected + PROTECTION_MOD_EXISTS = minetest.is_protected ~= old_is_protected --else fall back to old behaviour, where --worldedit privilege is permission to edit everything end) +--]] +local PROTECTION_MOD_EXISTS = false +mod.soft_depend("areas", function() + PROTECTION_MOD_EXISTS = true +end) +--mod.soft_depend("other protection mod goes here", function() +-- PROTECTION_MOD_EXISTS = true +--end) --[[ worldedit.privs replaces privs = {worldedit = true}, and also helps bypass volume permission checks. @@ -29,11 +38,9 @@ Returns: --privs={worldedit=true [, server=true]} --privs={worldedit=worldedit.priv() [, server=true]} --instead, I had to wrap the rest of func = . -worldedit.privs = function(--[[name, ]]privsfunc--[[, param]]) - --This runs a function for a chatcommand's func = , - --or it can be used directly in an if statement. +worldedit.privs = function(privsfunc) --returns a function (the argument function wrapped in another) which takes the arguments (name, param). if privsfunc == nil then - privsfunc = function(name, param) end + privsfunc = function() --[[no-op]] end end --this silly syntax was copied from safe_region, which is actually executed on chatcommand registration, and must return a function instead of the result of a function. @@ -44,13 +51,17 @@ worldedit.privs = function(--[[name, ]]privsfunc--[[, param]]) --The ability to set the whole world as owned by yourself is already potentially destructive, what's more destructive capability? privsfunc(name, param) return 2 --edit everywhere without checks - elseif not minetest.setting_getbool("creative_mode") or not PROTECTION_MOD_EXISTS then + end + local is_creative = minetest.setting_getbool("creative_mode") + if not is_creative or not PROTECTION_MOD_EXISTS then --no protection mod, or not the kind of world where people can just create nodes out of thin air, --worldedit privilege means editing anywhere if minetest.check_player_privs(name, {worldedit=true}) then privsfunc(name, param) return 2 --edit everywhere without checks else + --default chatcommand failure message + minetest.chat_send_player(name, "You don't have permission to run this command (missing privileges: worldedit)\nReasons:".. (is_creative and "" or " (not creative mode)") .. (PROTECTION_MOD_EXISTS and "" or " (no protection mod)")) --func(name, param) placeholder return nil --edit nowhere end @@ -69,13 +80,10 @@ end --so the region is defined per-command on exec. --//move has disconnected sections, so it's passed as a list of points. --which are deduplicated. -worldedit.can_edit_volume = function(--[[name, ]]volume, volfunc--[[, param]]) +worldedit.can_edit_volume = function(name, volume) --does not return a function like .privs does --volume is before func, unlike safe_region having func before count --because func may be removed to have can_edit_volume in an if statement --like worldedit.privs can be - if volfunc == nil then - volfunc = function(name, param) end - end --worldedit.privs was run once to prevent safe_region large area warnings, --then safe_region was run to prevent unnecessary large-scale permission checks @@ -83,14 +91,14 @@ worldedit.can_edit_volume = function(--[[name, ]]volume, volfunc--[[, param]]) --then worldedit.privs is run again to attempt skipping checks (resusing the same code) --then set is finally run. - return function(name, param) + --<==>--local returnfunc = function(name, param) --worldedit.privs said that 'name' can use worldedit at least somewhere -- return value 1 (or 2) before this function was run. --Try skipping volume permission checks. - local wp = worldedit.privs() + local wp = worldedit.privs(nil)(name, nil) if wp == 2 then - volfunc(name, param) + --volfunc(name, param) return true elseif wp == nil then --safety feature in case worldedit.can_edit_volume is ever run alone, without being surrounded by worldedit.privs() @@ -106,7 +114,15 @@ worldedit.can_edit_volume = function(--[[name, ]]volume, volfunc--[[, param]]) local has_worldedit = minetest.check_player_privs(name, {worldedit=true}) --all or nothing here - for i in volume do + --volume may be a single region (//set) or two possibly overlapping regions (//move) + --an overlapping //move is checked twice - any attempt to make it more efficient (by combining the volumes into a single two-pos one) may take into account that the format is //move axis amount, and break if the format is changed to //move xamount yamount zamount + for v = 1,3,2 do --volume[1] and volume[2] + if volume[v] ~= nil then --volume[3] and volume[4] + volume[v], volume[v+1] = worldedit.sort_pos(volume[v], volume[v+1]) + for y = volume[v].y, volume[v+1].y do + for z = volume[v].z, volume[v+1].z do + for x = volume[v].x, volume[v+1].x do + local node = {x=x, y=y, z=z} --[[ THIS SECTION IGNORES the distinction of area that is owned by someone else, but still editable this is treated as area owned by the editor, or no-man's land depending on if it's shared with one person or everyone @@ -117,11 +133,16 @@ worldedit.can_edit_volume = function(--[[name, ]]volume, volfunc--[[, param]]) --]] --Is it owned? - if minetest.is_protected(i) then + if minetest.is_protected(node, "") then --Is it someone else's? - if minetest.is_protected(i, name) then + if minetest.is_protected(node, name) then --already checked the ability to make it mine (areas) - minetest.chat_send_player(name, "Someone else owns at least part of what you want to edit") + minetest.chat_send_player(name, "You don't have permission to run this command ".. + "(Region "..minetest.pos_to_string(volume[1]).."-"..minetest.pos_to_string(volume[2]).. + (volume[3] ~= nil and ("+"..minetest.pos_to_string(volume[3]).."-"..minetest.pos_to_string(volume[4])) or "").. + " overlaps (first match) areaname: (x, y, z)-(x, y, z) owned by playername)".. + "\nReasons: (missing areas privilege)" + ) --volfunc(name, param) placeholder return false end @@ -130,18 +151,22 @@ worldedit.can_edit_volume = function(--[[name, ]]volume, volfunc--[[, param]]) --no-man's land --can I edit that? - elseif not has_worldedit then --use cached check - minetest.chat_send_player(name, "You can only edit area in which you own a plot (missing worldedit privilege)") + elseif not has_worldedit then --using cached check + minetest.chat_send_player(name, "You don't have permission to run this command (missing worldedit privilege)\nReasons: (At least part of this area is unowned (not owned by you)) (missing areas privilege)") --volfunc(name, param) placeholder return false end - end + end -- for x + end -- for z + end -- for y + end -- if not nil + end -- for v --the whole thing is --a) owned by me, and/or --b) owned by no one and I have the worldedit privilege. --c) I have the areas privilege and it's possibly owned by someone else. (returned earlier) - volfunc(name, param) + --volfunc(name, param) return true - end + --<==>--end end From 8bdb7f67d63f090edfa9341bf675f899ea06e561 Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Mon, 21 Apr 2014 13:28:10 -0700 Subject: [PATCH 14/17] Use worldedit.can_edit_volume for more commands (needs testing) Without the server privilege, files will be saved as worldedit.[we|mts] Ran into the problem of minetest.place_schematic not having a bounding box --- worldedit_commands/init.lua | 289 +++++++++++++++++++++++------------- 1 file changed, 184 insertions(+), 105 deletions(-) diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index c128dfb..944f7c5 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -324,11 +324,13 @@ minetest.register_chatcommand("/replace", { privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") - local newsearchnode = worldedit.normalize_nodename(searchnode) - local newreplacenode = worldedit.normalize_nodename(replacenode) - local count = worldedit.replace(pos1, pos2, newsearchnode, newreplacenode) - worldedit.player_notify(name, count .. " nodes replaced") + if worldedit.can_edit_volume(name, {pos1, pos2}) then + local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") + local newsearchnode = worldedit.normalize_nodename(searchnode) + local newreplacenode = worldedit.normalize_nodename(replacenode) + local count = worldedit.replace(pos1, pos2, newsearchnode, newreplacenode) + worldedit.player_notify(name, count .. " nodes replaced") + end end, check_replace)), }) @@ -338,11 +340,13 @@ minetest.register_chatcommand("/replaceinverse", { privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") - local newsearchnode = worldedit.normalize_nodename(searchnode) - local newreplacenode = worldedit.normalize_nodename(replacenode) - local count = worldedit.replaceinverse(pos1, pos2, searchnode, replacenode) - worldedit.player_notify(name, count .. " nodes replaced") + if worldedit.can_edit_volume(name, {pos1, pos2}) then + local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") + local newsearchnode = worldedit.normalize_nodename(searchnode) + local newreplacenode = worldedit.normalize_nodename(replacenode) + local count = worldedit.replaceinverse(pos1, pos2, searchnode, replacenode) + worldedit.player_notify(name, count .. " nodes replaced") + end end, check_replace)), }) @@ -368,9 +372,11 @@ minetest.register_chatcommand("/hollowsphere", { func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") - local node = get_node(name, nodename) - local count = worldedit.hollow_sphere(pos, tonumber(radius), node) - worldedit.player_notify(name, count .. " nodes added") + if worldedit.can_edit_volume(name, {{x=pos.x-radius, y=pos.y-radius, z=pos.z-radius}, {x=pos.x+radius, y=pos.y+radius, z=pos.z+radius}}) then + local node = get_node(name, nodename) + local count = worldedit.hollow_sphere(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end end, check_sphere)), }) @@ -381,9 +387,11 @@ minetest.register_chatcommand("/sphere", { func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") - local node = get_node(name, nodename) - local count = worldedit.sphere(pos, tonumber(radius), node) - worldedit.player_notify(name, count .. " nodes added") + if worldedit.can_edit_volume(name, {{x=pos.x-radius, y=pos.y-radius, z=pos.z-radius}, {x=pos.x+radius, y=pos.y+radius, z=pos.z+radius}}) then + local node = get_node(name, nodename) + local count = worldedit.sphere(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end end, check_sphere)), }) @@ -409,9 +417,11 @@ minetest.register_chatcommand("/hollowdome", { func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") - local node = get_node(name, nodename) - local count = worldedit.hollow_dome(pos, tonumber(radius), node) - worldedit.player_notify(name, count .. " nodes added") + if worldedit.can_edit_volume(name, {{x=pos.x-radius, y=pos.y, z=pos.z-radius}, {x=pos.x+radius, y=pos.y+radius, z=pos.z+radius}}) then + local node = get_node(name, nodename) + local count = worldedit.hollow_dome(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end end, check_dome)), }) @@ -422,9 +432,11 @@ minetest.register_chatcommand("/dome", { func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") - local node = get_node(name, nodename) - local count = worldedit.dome(pos, tonumber(radius), node) - worldedit.player_notify(name, count .. " nodes added") + if worldedit.can_edit_volume(name, {{x=pos.x-radius, y=pos.y, z=pos.z-radius}, {x=pos.x+radius, y=pos.y+radius, z=pos.z+radius}}) then + local node = get_node(name, nodename) + local count = worldedit.dome(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end end, check_dome)), }) @@ -455,9 +467,11 @@ minetest.register_chatcommand("/hollowcylinder", { axis, sign = worldedit.player_axis(name) length = length * sign end - local node = get_node(name, nodename) - local count = worldedit.hollow_cylinder(pos, axis, length, tonumber(radius), node) - worldedit.player_notify(name, count .. " nodes added") + if worldedit.can_edit_volume(name, {{x=pos.x-(axis~="x" and radius or 0), y=pos.y-(axis~="y" and radius or 0), z=pos.z-(axis~="z" and radius or 0)}, {x=pos.x+(axis~="x" and radius or length), y=pos.y+(axis~="y" and radius or length-1*sign), z=pos.z+(axis~="z" and radius or length-1*sign)}}) then + local node = get_node(name, nodename) + local count = worldedit.hollow_cylinder(pos, axis, length, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end end, check_cylinder)), }) @@ -473,9 +487,11 @@ minetest.register_chatcommand("/cylinder", { axis, sign = worldedit.player_axis(name) length = length * sign end - local node = get_node(name, nodename) - local count = worldedit.cylinder(pos, axis, length, tonumber(radius), node) - worldedit.player_notify(name, count .. " nodes added") + if worldedit.can_edit_volume(name, {{x=pos.x-(axis~="x" and radius or 0), y=pos.y-(axis~="y" and radius or 0), z=pos.z-(axis~="z" and radius or 0)}, {x=pos.x+(axis~="x" and radius or length-1*sign), y=pos.y+(axis~="y" and radius or length-1*sign), z=pos.z+(axis~="z" and radius or length-1*sign)}}) then + local node = get_node(name, nodename) + local count = worldedit.cylinder(pos, axis, length, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end end, check_cylinder)), }) @@ -491,9 +507,11 @@ minetest.register_chatcommand("/pyramid", { axis, sign = worldedit.player_axis(name) height = height * sign end - local node = get_node(name, nodename) - local count = worldedit.pyramid(pos, axis, height, node) - worldedit.player_notify(name, count .. " nodes added") + if worldedit.can_edit_volume(name, {{x=pos.x-(axis~="x" and height-1*sign or 0), y=pos.y-(axis~="y" and height-1*sign or 0), z=pos.z-(axis~="y" and height-1*sign or 0)}, {x=pos.x+height-1*sign, y=pos.y+height-1*sign, z=pos.z+height-1*sign}}) then + local node = get_node(name, nodename) + local count = worldedit.pyramid(pos, axis, height, node) + worldedit.player_notify(name, count .. " nodes added") + end end, function(name, param) if worldedit.pos1[name] == nil then @@ -519,9 +537,12 @@ minetest.register_chatcommand("/spiral", { func = worldedit.privs(safe_region(function(name, param) local pos = worldedit.pos1[name] local found, _, length, height, space, nodename = param:find("^(%d+)%s+(%d+)%s+(%d+)%s+(.+)$") - local node = get_node(name, nodename) - local count = worldedit.spiral(pos, tonumber(length), tonumber(height), tonumber(space), node) - worldedit.player_notify(name, count .. " nodes added") + local extent = math.ceil(length / 2) + if worldedit.can_edit_volume(name, {{x=0.5+pos.x-0.5-extent, y=pos.y, z=0.5+pos.z-0.5-extent}, {x=0.5+pos.x+0.5+extent, y=pos.y+height-1, z=0.5+pos.z+0.5+extent}}) then + local node = get_node(name, nodename) + local count = worldedit.spiral(pos, tonumber(length), tonumber(height), tonumber(space), node) + worldedit.player_notify(name, count .. " nodes added") + end end, function(name, param) if worldedit.pos1[name] == nil then @@ -555,9 +576,10 @@ minetest.register_chatcommand("/copy", { axis, sign = worldedit.player_axis(name) amount = amount * sign end - - local count = worldedit.copy(pos1, pos2, axis, amount) - worldedit.player_notify(name, count .. " nodes copied") + if worldedit.can_edit_volume(name, {{x=pos1.x+(axis=="x" and amount or 0), y=pos1.y+(axis=="y" and amount or 0), z=pos1.z+(axis=="z" and amount or 0)}, {x=pos2.x+(axis=="x" and amount or 0), y=pos2.y+(axis=="y" and amount or 0), z=pos2.z+(axis=="z" and amount or 0)}}) then + local count = worldedit.copy(pos1, pos2, axis, amount) + worldedit.player_notify(name, count .. " nodes copied") + end end, function(name, param) local volume = check_region(name, param) @@ -581,14 +603,15 @@ minetest.register_chatcommand("/move", { axis, sign = worldedit.player_axis(name) amount = amount * sign end + if worldedit.can_edit_volume(name, {pos1, pos2, {x=pos1.x+(axis=="x" and amount or 0), y=pos1.y+(axis=="y" and amount or 0), z=pos1.z+(axis=="z" and amount or 0)}, {x=pos2.x+(axis=="x" and amount or 0), y=pos2.y+(axis=="y" and amount or 0), z=pos2.z+(axis=="z" and amount or 0)}}) then + local count = worldedit.move(pos1, pos2, axis, amount) - local count = worldedit.move(pos1, pos2, axis, amount) - - pos1[axis] = pos1[axis] + amount - pos2[axis] = pos2[axis] + amount - worldedit.mark_pos1(name) - worldedit.mark_pos2(name) - worldedit.player_notify(name, count .. " nodes moved") + pos1[axis] = pos1[axis] + amount + pos2[axis] = pos2[axis] + amount + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + worldedit.player_notify(name, count .. " nodes moved") + end end, check_region)), }) @@ -604,8 +627,10 @@ minetest.register_chatcommand("/stack", { axis, sign = worldedit.player_axis(name) repetitions = repetitions * sign end - local count = worldedit.stack(pos1, pos2, axis, repetitions) - worldedit.player_notify(name, count .. " nodes stacked") + if worldedit.can_edit_volume(name, {{x=(axis=="x" and pos2.x+1*sign or pos1.x), y=(axis=="y" and pos2.y+1*sign or pos1.x), z=(axis=="z" and pos2.z+1*sign or pos1.z)}, {x=pos2.x+repetitions*(axis=="x" and pos2.x-pos1.x+1*sign or 0), y=pos2.y+repititions*(axis=="y" and pos2.y-pos1.y+1*sign or 0), z=pos2.z+repititions*(axis=="z" and pos2.z-pos1.z+1*sign or 0)}}) then + local count = worldedit.stack(pos1, pos2, axis, repetitions) + worldedit.player_notify(name, count .. " nodes stacked") + end end, function(name, param) local found, _, axis, repetitions = param:find("^([xyz%?])%s+([+-]?%d+)$") @@ -626,15 +651,17 @@ minetest.register_chatcommand("/stretch", { local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, stretchx, stretchy, stretchz = param:find("^(%d+)%s+(%d+)%s+(%d+)$") stretchx, stretchy, stretchz = tonumber(stretchx), tonumber(stretchy), tonumber(stretchz) - local count, pos1, pos2 = worldedit.stretch(pos1, pos2, stretchx, stretchy, stretchz) + if worldedit.can_edit_volume(name, {pos1, {x=pos1.x + (pos2.x - pos1.x) * stretchx, y=pos1.y + (pos2.y - pos1.y) * stretchy, z=pos1.z + (pos2.z - pos1.z) * stretchz}}) then + local count, pos1, pos2 = worldedit.stretch(pos1, pos2, stretchx, stretchy, stretchz) - --reset markers to scaled positions - worldedit.pos1[name] = pos1 - worldedit.pos2[name] = pos2 - worldedit.mark_pos1(name) - worldedit.mark_pos2(name) + --reset markers to scaled positions + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) - worldedit.player_notify(name, count .. " nodes stretched") + worldedit.player_notify(name, count .. " nodes stretched") + end end, function(name, param) local found, _, stretchx, stretchy, stretchz = param:find("^(%d+)%s+(%d+)%s+(%d+)$") @@ -661,15 +688,29 @@ minetest.register_chatcommand("/transpose", { local found, _, axis1, axis2 = param:find("^([xyz%?])%s+([xyz%?])$") if axis1 == "?" then axis1 = worldedit.player_axis(name) end if axis2 == "?" then axis2 = worldedit.player_axis(name) end - local count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2) + local notaxis = (axis1~="x" and axis2~="x") and "x" or ( + (axis1~="y" and axis2~="y") and "y" or ( + (axis1~="z" and axis2~="z") and "z" or ( + assert(0) + ) + ) + ) + local side = math.max( --does not include pos1 in the length + (axis2=="x" or "x"==axis1) and pos2.x-pos1.x or 0, + (axis2=="y" or "y"==axis1) and pos2.y-pos1.y or 0, + (axis2=="z" or "z"==axis1) and pos2.z-pos1.z or 0 + ) + if worldedit.can_edit_volume(name, {pos1, {x=notaxis=="x" and pos2.x or pos1.x+side, y=notaxis=="y" and pos2.y or pos1.y+side, z=notaxis=="z" and pos2.z or pos1.z+side}}) then + local count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2) - --reset markers to transposed positions - worldedit.pos1[name] = pos1 - worldedit.pos2[name] = pos2 - worldedit.mark_pos1(name) - worldedit.mark_pos2(name) + --reset markers to transposed positions + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) - worldedit.player_notify(name, count .. " nodes transposed") + worldedit.player_notify(name, count .. " nodes transposed") + end end, function(name, param) local found, _, axis1, axis2 = param:find("^([xyz%?])%s+([xyz%?])$") @@ -692,8 +733,10 @@ minetest.register_chatcommand("/flip", { func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] if param == "?" then param = worldedit.player_axis(name) end - local count = worldedit.flip(pos1, pos2, param) - worldedit.player_notify(name, count .. " nodes flipped") + if worldedit.can_edit_volume(name, {pos1, pos2}) then + local count = worldedit.flip(pos1, pos2, param) + worldedit.player_notify(name, count .. " nodes flipped") + end end, function(name, param) if param ~= "x" and param ~= "y" and param ~= "z" and param ~= "?" then @@ -712,15 +755,22 @@ minetest.register_chatcommand("/rotate", { local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis, angle = param:find("^([xyz%?])%s+([+-]?%d+)$") if axis == "?" then axis = worldedit.player_axis(name) end - local count, pos1, pos2 = worldedit.rotate(pos1, pos2, axis, angle) + local side = math.max( + axis~="x" and pos2.x-pos1.x or 0, + axis~="y" and pos2.y-pos1.y or 0, + axis~="z" and pos2.z-pos1.z or 0 + ) + if worldedit.can_edit_volume(name, {pos1, {x=axis=="x" and pos2.x or pos1.x+side, y=axis=="y" and pos22.y or pos1.y+side, z=axis=="z" and pos2.z or pos1.z+side}}) then + local count, pos1, pos2 = worldedit.rotate(pos1, pos2, axis, angle) - --reset markers to rotated positions - worldedit.pos1[name] = pos1 - worldedit.pos2[name] = pos2 - worldedit.mark_pos1(name) - worldedit.mark_pos2(name) + --reset markers to rotated positions + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) - worldedit.player_notify(name, count .. " nodes rotated") + worldedit.player_notify(name, count .. " nodes rotated") + end end, function(name, param) local found, _, axis, angle = param:find("^([xyz%?])%s+([+-]?%d+)$") @@ -743,8 +793,10 @@ minetest.register_chatcommand("/orient", { func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, angle = param:find("^([+-]?%d+)$") - local count = worldedit.orient(pos1, pos2, angle) - worldedit.player_notify(name, count .. " nodes oriented") + if worldedit.can_edit_volume(name, {pos1, pos2}) then + local count = worldedit.orient(pos1, pos2, angle) + worldedit.player_notify(name, count .. " nodes oriented") + end end, function(name, param) local found, _, angle = param:find("^([+-]?%d+)$") @@ -766,8 +818,10 @@ minetest.register_chatcommand("/fixlight", { privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - local count = worldedit.fixlight(pos1, pos2) - worldedit.player_notify(name, count .. " nodes updated") + if worldedit.can_edit_volume(name, {pos1, pos2}) then + local count = worldedit.fixlight(pos1, pos2) + worldedit.player_notify(name, count .. " nodes updated") + end end)), }) @@ -777,8 +831,10 @@ minetest.register_chatcommand("/hide", { privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - local count = worldedit.hide(pos1, pos2) - worldedit.player_notify(name, count .. " nodes hidden") + if worldedit.can_edit_volume(name, {pos1, pos2}) then + local count = worldedit.hide(pos1, pos2) + worldedit.player_notify(name, count .. " nodes hidden") + end end)), }) @@ -788,9 +844,11 @@ minetest.register_chatcommand("/suppress", { privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - local node = get_node(name, param) - local count = worldedit.suppress(pos1, pos2, node) - worldedit.player_notify(name, count .. " nodes suppressed") + if worldedit.can_edit_volume(name, {pos1, pos2}) then + local node = get_node(name, param) + local count = worldedit.suppress(pos1, pos2, node) + worldedit.player_notify(name, count .. " nodes suppressed") + end end, check_set)), }) @@ -800,9 +858,11 @@ minetest.register_chatcommand("/highlight", { privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - local node = get_node(name, param) - local count = worldedit.highlight(pos1, pos2, node) - worldedit.player_notify(name, count .. " nodes highlighted") + if worldedit.can_edit_volume(name, {pos1, pos2}) then + local node = get_node(name, param) + local count = worldedit.highlight(pos1, pos2, node) + worldedit.player_notify(name, count .. " nodes highlighted") + end end, check_set)), }) @@ -812,24 +872,31 @@ minetest.register_chatcommand("/restore", { privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - local count = worldedit.restore(pos1, pos2) - worldedit.player_notify(name, count .. " nodes restored") + if worldedit.can_edit_volume(name, {pos1, pos2}) then + local count = worldedit.restore(pos1, pos2) + worldedit.player_notify(name, count .. " nodes restored") + end end)), }) minetest.register_chatcommand("/save", { params = "", description = "Save the current WorldEdit region to \"(world folder)/schems/.we\"", - privs = {server=true}, + privs = {}, --worldedit, server func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - if param == "" then - worldedit.player_notify(name, "invalid usage: " .. param) - return - end - if not string.find(param, "^[%w \t.,+-_=!@#$%%^&*()%[%]{};'\"]+$") then - worldedit.player_notify(name, "invalid file name: " .. param) - return + if minetest.check_player_privs(name, {server=true}) then + if param == "" then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + if not string.find(param, "^[%w \t.,+-_=!@#$%%^&*()%[%]{};'\"]+$") then + worldedit.player_notify(name, "invalid file name: " .. param) + return + end + else + worldedit.player_notify(name, "saving as worldedit.we (missing privileges: server)") + param = "worldedit" end local result, count = worldedit.serialize(pos1, pos2) @@ -934,9 +1001,12 @@ minetest.register_chatcommand("/load", { return end - local count = worldedit.deserialize(pos, value) + local nodepos1, nodepos2, _ = worldedit.allocate(pos, value) + if worldedit.can_edit_volume(name, {nodepos1, nodepos2}) then + local count = worldedit.deserialize(pos, value) - worldedit.player_notify(name, count .. " nodes loaded") + worldedit.player_notify(name, count .. " nodes loaded") + end end), }) @@ -983,12 +1053,17 @@ minetest.register_chatcommand("/luatransform", { minetest.register_chatcommand("/mtschemcreate", { params = "", description = "Save the current WorldEdit region using the Minetest Schematic format to \"(world folder)/schems/.mts\"", - privs = {server=true}, + privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - if param == nil then - worldedit.player_notify(name, "No filename specified") - return + if minetest.check_player_privs(name, {server=true}) then + if param == nil then + worldedit.player_notify(name, "No filename specified") + return + end + else + worldedit.player_notify(name, "saving as worldedit.mts (missing privileges: server)") + param = "worldedit" end local path = minetest.get_worldpath() .. "/schems" @@ -1020,12 +1095,14 @@ minetest.register_chatcommand("/mtschemplace", { if pos == nil then return end local path = minetest.get_worldpath() .. "/schems/" .. param .. ".mts" - if minetest.place_schematic(pos, path) == nil then - worldedit.player_notify(name, "failed to place Minetest schematic", false) - else - worldedit.player_notify(name, "placed Minetest schematic " .. param .. - " at " .. minetest.pos_to_string(pos), false) - end + --if worldedit.can_edit_volume(name, {pos1, ?}) then + if minetest.place_schematic(pos, path) == nil then + worldedit.player_notify(name, "failed to place Minetest schematic", false) + else + worldedit.player_notify(name, "placed Minetest schematic " .. param .. + " at " .. minetest.pos_to_string(pos), false) + end + --end end), }) @@ -1076,7 +1153,9 @@ minetest.register_chatcommand("/clearobjects", { privs = {}, func = worldedit.privs(safe_region(function(name, param) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - local count = worldedit.clearobjects(pos1, pos2) - worldedit.player_notify(name, count .. " objects cleared") + if worldedit.can_edit_volume(name, {pos1, pos2}) then + local count = worldedit.clearobjects(pos1, pos2) + worldedit.player_notify(name, count .. " objects cleared") + end end)), }) From 589922a341b1e1016004d6d3a5e1ba737fc943d0 Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Mon, 21 Apr 2014 14:23:33 -0700 Subject: [PATCH 15/17] Allocate space for .mts similarly to .we (also needs testing) --- worldedit_commands/init.lua | 38 +++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index 944f7c5..7378889 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -1081,6 +1081,36 @@ minetest.register_chatcommand("/mtschemcreate", { end)), }) +minetest.allocate_schematic = function(originpos, schematic) + --[[ + u32 MTSM + u16 version 3 + u16 x + u16 y + u16 z + ... + --]] + --8 bits in a byte + local offset = 0 + if string.byte(schematic, offset+1, offset+32/8) == "MTSM" then --32 bits + offset = offset + 32/8 + if string.byte(schematic, offset+1, offset+16/8) == "3" then + offset = offset + 16/8 + local x = string.byte(schematic, offset+1, offset+16/8) + offset = offset + 16/8 + local y = string.byte(schematic, offset+1, offset+16/8) + offset = offset + 16/8 + local z = string.byte(schematic, offset+1, offset+16/8) + offset = offset + 16/8 + return originpos, {x=originpos.x+x, y=originpos.y+y, z=originpos.z+z} + else + --not version 3 + end + else + --not a schematic? + end +end + minetest.register_chatcommand("/mtschemplace", { params = "", description = "Load nodes from \"(world folder)/schems/.mts\" with position 1 of the current WorldEdit region as the origin", @@ -1095,14 +1125,18 @@ minetest.register_chatcommand("/mtschemplace", { if pos == nil then return end local path = minetest.get_worldpath() .. "/schems/" .. param .. ".mts" - --if worldedit.can_edit_volume(name, {pos1, ?}) then + + local value = file:read("*a") + file:close() + + if worldedit.can_edit_volume(name, {minetest.allocate_schematic(pos, value)}) then if minetest.place_schematic(pos, path) == nil then worldedit.player_notify(name, "failed to place Minetest schematic", false) else worldedit.player_notify(name, "placed Minetest schematic " .. param .. " at " .. minetest.pos_to_string(pos), false) end - --end + end end), }) From da867d7fd49260b265d0abed918ac6935fad5089 Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Mon, 21 Apr 2014 21:02:03 -0700 Subject: [PATCH 16/17] README --- worldedit_protection/README.txt | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 worldedit_protection/README.txt diff --git a/worldedit_protection/README.txt b/worldedit_protection/README.txt new file mode 100644 index 0000000..734223a --- /dev/null +++ b/worldedit_protection/README.txt @@ -0,0 +1,38 @@ +Because worldedit can easily cause massive destruction when in the wrong hands, the only use it has seen outside of singleplayer games is when wielded by an admin or moderator. +I (khonkhortisan) intend to change that, by tying its use to, and making it respect, owned areas: + On a non-creative server (say, survival) it does not make sense to be able to create valuable ores out of thin air, so the "worldedit" privilege is required to do anything. + On a creative server that does not have any form of land ownership, the "worldedit" privilege is required to do anything. A malicious player is limited by the speed of their arm. + On a creative server that has an ownership mod (say, areas) the ability to use worldedit is more complicated than a simple "yes" or "no": + Commands that do not actually edit nodes can be used by anyone. This includes setting the region, inspecting nodes, saving (to a standard filename, see below) and copying (the initial region with //copy or //stack) + Commands that do edit nodes check the current worldedit region (or the bounding box for the command) for the player's ability both to edit manually, and through this mod: (this includes the second region with //copy or //stack) + If the region is completely contained by area assigned to you, the command succeeds. + If the whole region is not owned by anyone (with or without part of it being owned by you): + If you do not have the "worldedit" privilege, you can only edit area you fully own, and the command fails. + If you do have the "worldedit" privilege, you can edit unowned area and/or your area (but not someone else's area), and the command succeeds. + If part of the region is owned by someone else (with or without part of it being unowned, or owned by you): + If you have the "areas" privilege, you could make yourself the owner anyway, so the command succeeds. + If you do not have the "areas" privilege, the land cannot be edited by you (worldedit does not currently understand owned but shared area?) + File writes - if you can set a region, you can read from the world. + If you have the "server" privilege, you can save to an arbitrary filename, as usual. + If you do not have the "server" privilege, the filename is forced to "worldedit.we" or "worldedit.mts". + File reads (of *.we or *.mts, of course) will succeed, but must pass the region write check. + Lua commands (//lua and //luatransform) require first "server", then "admin", as usual. + +minetest.register_chatcommand + privs = {worldedit}, is what it used to have, but that privilege is only required in certain cases (see above) + privs = {}, func = worldedit.privs(function(name, param)...end), passes to func a wrapper that checks first whether the worldedit privilege is required, then if the player has it, before running the inner function. + +worldedit.privs can also be used in an if statement, as it returns both whether execution should continue (nil or 1), and whether a region permission check should be skipped (2) due to the areas privilege. + +worldedit.can_edit_volume + It takes the player's name, then a list of either two or four points (two points per region, //move has two regions to check) + It re-runs worldedit.privs to attempt skipping a region permission check (if the player has the "areas" privilege) + This return value should probably be cached instead of running the function twice. + func = worldedit.privs(safe_region(function(name, param)...if worldedit.can_edit_volume(name, {pos1, pos2}) then... + The "wp" return value has to make it past safe_region somehow. + It returns whether the command should actually be run, along with telling the player why it wasn't. + +minetest.allocate_schematic + A function for schematics corresponding with worldedit.allocate for .we files + + From ede4c76db46b6b9c6493702c2ab7a22025fb910e Mon Sep 17 00:00:00 2001 From: khonkhortisan Date: Tue, 22 Apr 2014 13:36:46 -0700 Subject: [PATCH 17/17] initialize sign fix spelling error in variable debug info for testing --- worldedit_commands/init.lua | 8 +++++++- worldedit_protection/init.lua | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index 7378889..3cea7cb 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -463,6 +463,7 @@ minetest.register_chatcommand("/hollowcylinder", { local pos = worldedit.pos1[name] local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$") length = tonumber(length) + sign = 1 if axis == "?" then axis, sign = worldedit.player_axis(name) length = length * sign @@ -483,6 +484,7 @@ minetest.register_chatcommand("/cylinder", { local pos = worldedit.pos1[name] local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$") length = tonumber(length) + sign = 1 if axis == "?" then axis, sign = worldedit.player_axis(name) length = length * sign @@ -503,6 +505,7 @@ minetest.register_chatcommand("/pyramid", { local pos = get_position(name) local found, _, axis, height, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(.+)$") height = tonumber(height) + sign = 1 if axis == "?" then axis, sign = worldedit.player_axis(name) height = height * sign @@ -572,6 +575,7 @@ minetest.register_chatcommand("/copy", { return end amount = tonumber(amount) + sign = 1 if axis == "?" then axis, sign = worldedit.player_axis(name) amount = amount * sign @@ -599,6 +603,7 @@ minetest.register_chatcommand("/move", { return end amount = tonumber(amount) + sign = 1 if axis == "?" then axis, sign = worldedit.player_axis(name) amount = amount * sign @@ -623,11 +628,12 @@ minetest.register_chatcommand("/stack", { local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] local found, _, axis, repetitions = param:find("^([xyz%?])%s+([+-]?%d+)$") repetitions = tonumber(repetitions) + sign = 1 if axis == "?" then axis, sign = worldedit.player_axis(name) repetitions = repetitions * sign end - if worldedit.can_edit_volume(name, {{x=(axis=="x" and pos2.x+1*sign or pos1.x), y=(axis=="y" and pos2.y+1*sign or pos1.x), z=(axis=="z" and pos2.z+1*sign or pos1.z)}, {x=pos2.x+repetitions*(axis=="x" and pos2.x-pos1.x+1*sign or 0), y=pos2.y+repititions*(axis=="y" and pos2.y-pos1.y+1*sign or 0), z=pos2.z+repititions*(axis=="z" and pos2.z-pos1.z+1*sign or 0)}}) then + if worldedit.can_edit_volume(name, {{x=(axis=="x" and pos2.x+1*sign or pos1.x), y=(axis=="y" and pos2.y+1*sign or pos1.x), z=(axis=="z" and pos2.z+1*sign or pos1.z)}, {x=pos2.x+repetitions*(axis=="x" and pos2.x-pos1.x+1*sign or 0), y=pos2.y+repetitions*(axis=="y" and pos2.y-pos1.y+1*sign or 0), z=pos2.z+repetitions*(axis=="z" and pos2.z-pos1.z+1*sign or 0)}}) then local count = worldedit.stack(pos1, pos2, axis, repetitions) worldedit.player_notify(name, count .. " nodes stacked") end diff --git a/worldedit_protection/init.lua b/worldedit_protection/init.lua index fb8fcc2..6480b9a 100644 --- a/worldedit_protection/init.lua +++ b/worldedit_protection/init.lua @@ -81,6 +81,12 @@ end --//move has disconnected sections, so it's passed as a list of points. --which are deduplicated. worldedit.can_edit_volume = function(name, volume) --does not return a function like .privs does + --debug info, remove after testing + minetest.chat_send_player(name, minetest.pos_to_string(volume[1])..minetest.pos_to_string(volume[2])) + if volume[3] ~= nil then + minetest.chat_send_player(name, minetest.pos_to_string(volume[3])..minetest.pos_to_string(volume[4])) + end + --volume is before func, unlike safe_region having func before count --because func may be removed to have can_edit_volume in an if statement --like worldedit.privs can be