1
0
mirror of https://github.com/Uberi/Minetest-WorldEdit.git synced 2025-08-19 22:50:21 +02:00

17 Commits

Author SHA1 Message Date
2f535dd053 worldedit: Document inner working of worldedit.keep_loaded 2020-05-25 19:48:54 +02:00
867cd6edc7 Improve node name normalization again
so that "desert stone" won't select "desert stone block"
2020-05-12 21:53:01 +02:00
4918610c43 Fix rotate in worldedit GUI 2020-05-12 21:29:51 +02:00
edd27636a6 Do not allow //mix with no nodes 2020-05-09 22:34:29 +02:00
7d0811fd47 Update help texts to be consistent 2020-04-26 16:53:55 +02:00
4d08a1cc55 Implement //cubeapply with three side lengths 2020-04-26 16:01:07 +02:00
34844b2d38 Set static_save = false for marker entities 2020-04-16 23:50:15 +02:00
0f5dcc790d Implement //clearcut to delete trees, plants from generated terrain
closes #165
2020-04-07 03:05:30 +02:00
37de177f72 Fix off-by-one in //cubeapply 2020-04-07 00:46:13 +02:00
f285a55dd5 Improve brush command error messages 2020-04-07 00:38:11 +02:00
9b26034aea Move worldedit.marker_update
Markers are part of the UI (`worldedit_chatcommands`) and do not belong in `worldedit`.
2020-04-07 00:14:31 +02:00
963a9f6b96 Implement //cubeapply 2020-04-06 23:32:11 +02:00
5e8bfd5166 Improve node name normalization in case of multi-line descriptions 2020-03-29 21:55:47 +02:00
06a3b63578 GUI command execution: Do not ignore chatcommand return values
Additionally, this commit makes the command execution more modular,
so it is e.g. possible to implement something to disable the
many nodes confirmation after setting a checkbox in the formspec.
2020-03-09 15:33:19 +01:00
5e47af8773 Make region marker entities withstand TNT explosions
Also fixes a crash when detonating TNT near them though this is
not our fault and the proper fix is pending in minetest_game.
2020-03-06 21:20:15 +01:00
da51c688d2 Call minetest.deserialize with safe=true
wtf?
2020-02-06 11:53:14 +01:00
ab93871877 Move some deserialization code around 2020-02-06 11:51:44 +01:00
9 changed files with 434 additions and 210 deletions

View File

@ -29,24 +29,26 @@ Many commands also have shorter names that can be typed faster. For example, if
### `//about`
Get information about the mod.
Get information about the WorldEdit mod.
//about
### `//inspect on/off/1/0/true/false/yes/no/enable/disable/<blank>`
### `//help [all/<cmd>]`
Get help for WorldEdit commands. `all` shows all WorldEdit commands, `<cmd>`
the help text for the given command.
//help
//help all
//help hollowpyramid
### `//inspect [on/off/1/0/true/false/yes/no/enable/disable]`
Enable or disable node inspection.
//inspect on
//inspect off
//inspect 1
//inspect 0
//inspect true
//inspect false
//inspect yes
//inspect no
//inspect enable
//inspect disable
//inspect
### `//reset`
@ -81,18 +83,19 @@ Set WorldEdit region position 2 to the player's location.
### `//p set/set1/set2/get`
Set WorldEdit region, WorldEdit position 1, or WorldEdit position 2 by punching nodes, or display the current WorldEdit region.
Set WorldEdit region, WorldEdit position 1, or WorldEdit position 2 by
punching nodes, or print the current WorldEdit region.
//p set
//p set1
//p set2
//p get
### `//fixedpos set1 x y z`
### `//fixedpos set1/set2 <x> <y> <z>`
Set a WorldEdit region position to the position at (`<x>`, `<y>`, `<z>`).
Set the WorldEdit region position 1 or 2 to the position (`<x>`, `<y>`, `<z>`).
//fixedpos set1 0 0 0
//fixedpos set1 0 0 0
//fixedpos set1 -30 5 28
//fixedpos set2 1004 -200 432
@ -121,9 +124,12 @@ Set the current WorldEdit region to `<node>`.
Set the param2 value of all nodes in the current WorldEdit region to `<param2>`.
### `//mix <node1> [<count1>] <node2> [<count2>]...`
//param2 8
Fill the current WorldEdit region with a random mix of `<node1>`, `<node2>`, `...`. Weightings can be optionally specified via a number after a node name.
### `//mix <node1> [count1] <node2> [count2] ...`
Fill the current WorldEdit region with a random mix of `<node1>`, `<node2>`, `...`.
Weightings can be optionally specified via the `[count1]`, `[count2]`, `...` parameters after a node name.
//mix air
//mix cactus stone glass sandstone
@ -152,13 +158,15 @@ Replace all nodes other than `<search node>` with `<replace node>` in the curren
### `//hollowcube <width> <height> <length> <node>`
Adds a hollow cube with its ground level centered at WorldEdit position 1 with dimensions `<width>` x `<height>` x `<length>`, composed of `<node>`.
Adds a hollow cube with its ground level centered at WorldEdit position 1 with
dimensions `<width>` x `<height>` x `<length>`, composed of `<node>`.
//hollowcube 6 5 6 Diamond Block
### `//cube <width> <height> <length> <node>`
Adds a cube with its ground level centered at WorldEdit position 1 with dimensions `<width>` x `<height>` x `<length>`, composed of `<node>`.
Adds a cube with its ground level centered at WorldEdit position 1 with
dimensions `<width>` x `<height>` x `<length>`, composed of `<node>`.
//cube 6 5 6 Diamond Block
//cube 7 2 1 default:cobble
@ -197,7 +205,8 @@ Add dome centered at WorldEdit position 1 with radius `<radius>`, composed of `<
### `//hollowcylinder x/y/z/? <length> <radius1> [radius2] <node>`
Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length `<length>`, base radius `<radius1>` (and top radius `[radius2]`), composed of `<node>`.
Add hollow cylinder at WorldEdit position 1 along the given axis with length `<length>`,
base radius `<radius1>` (and top radius `[radius2]`), composed of `<node>`.
Despite its name this command allows you to create cones (`radius2` = 0) as well as any shapes inbetween (0 < `radius2` < `radius1`).
Swapping `radius1` and `radius2` will create the same object but upside-down.
@ -213,7 +222,8 @@ Swapping `radius1` and `radius2` will create the same object but upside-down.
### `//cylinder x/y/z/? <length> <radius1> [radius2] <node>`
Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length `<length>`, base radius `<radius1>` (and top radius `[radius2]`), composed of `<node>`.
Add cylinder at WorldEdit position 1 along the given axis with length `<length>`,
base radius `<radius1>` (and top radius `[radius2]`), composed of `<node>`.
Can also create shapes other than cylinders, e.g. cones (see documentation above).
//cylinder x +5 8 Bronze Block
@ -225,18 +235,18 @@ Can also create shapes other than cylinders, e.g. cones (see documentation above
//cylinder x 6 0 5 Dirt
//cylinder z 20 10 20 default:desert_stone
### `//hollowpyramid x/y/z? <height> <node>`
### `//hollowpyramid x/y/z/? <height> <node>`
Add hollow pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height `<height>`, composed of `<node>`.
Add hollow pyramid centered at WorldEdit position 1 along the given axis with height `<height>` composed of `<node>`.
//hollowpyramid x 8 Diamond Block
//hollowpyramid y -5 glass
//hollowpyramid z 2 mesecons:wire_00000000_off
//hollowpyramid ? 12 mesecons:wire_00000000_off
### `//pyramid x/y/z? <height> <node>`
### `//pyramid x/y/z/? <height> <node>`
Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height `<height>`, composed of `<node>`.
Add pyramid centered at WorldEdit position 1 along the given axis with height `<height>` composed of `<node>`.
//pyramid x 8 Diamond Block
//pyramid y -5 glass
@ -245,7 +255,8 @@ Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height
### `//spiral <length> <height> <spacer> <node>`
Add spiral centered at WorldEdit position 1 with side length `<length>`, height `<height>`, space between walls `<spacer>`, composed of `<node>`.
Add spiral centered at WorldEdit position 1 with side length `<length>`,
height `<height>`, space between walls `<spacer>`, composed of `<node>`.
//spiral 20 5 3 Diamond Block
//spiral 5 2 1 glass
@ -253,7 +264,7 @@ Add spiral centered at WorldEdit position 1 with side length `<length>`, height
### `//copy x/y/z/? <amount>`
Copy the current WorldEdit region along the x/y/z/? axis by `<amount>` nodes.
Copy the current WorldEdit region along the given axis by `<amount>` nodes.
//copy x 15
//copy y -7
@ -262,7 +273,7 @@ Copy the current WorldEdit region along the x/y/z/? axis by `<amount>` nodes.
### `//move x/y/z/? <amount>`
Move the current WorldEdit positions and region along the x/y/z/? axis by `<amount>` nodes.
Move the current WorldEdit positions and region along the given axis by `<amount>` nodes.
//move x 15
//move y -7
@ -271,7 +282,7 @@ Move the current WorldEdit positions and region along the x/y/z/? axis by `<amou
### `//stack x/y/z/? <count>`
Stack the current WorldEdit region along the x/y/z/? axis `<count>` times.
Stack the current WorldEdit region along the given axis `<count>` times.
//stack x 3
//stack y -1
@ -287,7 +298,9 @@ Stack the current WorldEdit region `<count>` times by offset `<x>`, `<y>`, `<z>`
### `//stretch <stretchx> <stretchy> <stretchz>`
Scale the current WorldEdit positions and region by a factor of `<stretchx>`, `<stretchy>`, `<stretchz>` along the X, Y, and Z axes, repectively, with position 1 as the origin.
Scale the current WorldEdit positions and region by a factor of
`<stretchx>`, `<stretchy>`, `<stretchz>` along the X, Y, and Z axes,
respectively, with position 1 as the origin.
//stretch 2 2 2
//stretch 1 2 1
@ -295,25 +308,22 @@ Scale the current WorldEdit positions and region by a factor of `<stretchx>`, `<
### `//transpose x/y/z/? x/y/z/?`
Transpose the current WorldEdit positions and region along the x/y/z/? and x/y/z/? axes.
Transpose the current WorldEdit positions and region along given axes.
//transpose x y
//transpose x z
//transpose y z
//transpose ? y
### `//flip x/y/z/?`
Flip the current WorldEdit region along the x/y/z/? axis.
Flip the current WorldEdit region along the given axis.
//flip x
//flip y
//flip z
//flip ?
### `//rotate x/y/z/? <angle>`
Rotate the current WorldEdit positions and region along the x/y/z/? axis by angle `<angle>` (90 degree increment).
Rotate the current WorldEdit positions and region along the given axis by angle `<angle>` (90 degree increment).
//rotate x 90
//rotate y 180
@ -341,6 +351,13 @@ Removes any fluid node within the current WorldEdit region.
//drain
### `//clearcut`
Removes any plant, tree or foilage-like nodes in the selected region.
The idea is to remove anything that isn't part of the terrain, leaving a "natural" empty space ready for building.
//clearcut
### `//hide`
Hide all nodes in the current WorldEdit region non-destructively.
@ -349,7 +366,7 @@ Hide all nodes in the current WorldEdit region non-destructively.
### `//suppress <node>`
Suppress all <node> in the current WorldEdit region non-destructively.
Suppress all `<node>` in the current WorldEdit region non-destructively.
//suppress Diamond Block
//suppress glass
@ -357,7 +374,7 @@ Suppress all <node> in the current WorldEdit region non-destructively.
### `//highlight <node>`
Highlight <node> in the current WorldEdit region by hiding everything else non-destructively.
Highlight `<node>` in the current WorldEdit region by hiding everything else non-destructively.
//highlight Diamond Block
//highlight glass
@ -401,8 +418,8 @@ Executes `<code>` as a Lua chunk in the global namespace.
Executes `<code>` as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region.
//luatransform minetest.add_node(pos, {name="default:stone"})
//luatransform if minetest.get_node(pos).name == "air" then minetest.add_node(pos, {name="default:water_source"})
//luatransform minetest.swap_node(pos, {name="default:stone"})
//luatransform if minetest.get_node(pos).name == "air" then minetest.add_node(pos, {name="default:water_source"}) end
### `//mtschemcreate <file>`
@ -431,42 +448,44 @@ Clears all objects within the WorldEdit region.
//clearobjects
### `//shift x/y/z/?/up/down/left/right/front/back [+|-]<amount>`
### `//shift x/y/z/?/up/down/left/right/front/back [+/-]<amount>`
Shifts the selection area by `[+|-]<amount>` without touching its contents. The shifting axis can be absolute (`x/y/z`) or
relative (`up/down/left/right/front/back`).
Shifts the selection area by `[+|-]<amount>` without moving its contents.
The shifting axis can be absolute (`x/y/z`) or relative (`up/down/left/right/front/back`).
//shift left 5
### `//expand [+|-]x/y/z/?/up/down/left/right/front/back <amount> [reverse-amount]`
### `//expand [+/-]x/y/z/?/up/down/left/right/front/back <amount> [reverse amount]`
Expands the selection by `<amount>` in the selected absolute or relative axis. If specified, the selection can be expanded in the
opposite direction over the same axis by `[reverse-amount]`.
Expands the selection by `<amount>` in the selected absolute or relative axis.
If specified, the selection can be expanded in the opposite direction over the same axis by `[reverse amount]`.
//expand right 7 5
### `//contract [+|-]x/y/z/?/up/down/left/right/front/back <amount> [reverse-amount]`
### `//contract [+/-]x/y/z/?/up/down/left/right/front/back <amount> [reverse amount]`
Contracts the selection by `<amount>` in the selected absolute or relative axis. If specified, the selection can be contracted in the
opposite direction over the same axis by `[reverse-amount]`.
Contracts the selection by `<amount>` in the selected absolute or relative axis.
If specified, the selection can be contracted in the opposite direction over the same axis by `[reverse amount]`.
//expand right 7 5
### `//outset [hv] <amount>`
### `//outset [h/v] <amount>`
Expands the selection in all directions by `<amount>`. If specified, the selection can be expanded horizontally in the x and z axes `[h]`
or vertically in the y axis `[v]`.
Expands the selection in all directions by `<amount>`. If specified,
the selection can be expanded horizontally in the x and z axes using `h`
or vertically in the y axis using `v`.
//outset v 5
### `//inset [hv] <amount>`
### `//inset [h/v] <amount>`
Contracts the selection in all directions by `<amount>`. If specified, the selection can be contracted horizontally in the x and z axes `[h]`
or vertically in the y axis `[v]`.
Contracts the selection in all directions by `<amount>`. If specified,
the selection can be contracted horizontally in the x and z axes using `h`
or vertically in the y axis using `v`.
//outset v 5
//inset h 5
### `//brush none/<command> [parameters]`
### `//brush none/(<command> [parameters])`
Assigns the given `<command>` to the currently held brush item, it will be ran with the first pointed solid node (as determined via raycast) as
WorldEdit position 1 when using that specific brush item.
@ -476,3 +495,14 @@ Note that this functionality requires the `worldedit_brush` mod enabled.
//brush cube 8 8 8 Cobblestone
//brush spr 12 glass
//brush none
### `//cubeapply <size>/(<sizex> <sizey> <sizez>) <command> [parameters]`
Selects a cube with side length of `<size>` around the WorldEdit position 1 and runs the given `<command>` on the newly selected region.
If `<sizex>`, `<sizey>` and `<sizez>` are given, they instead specify the length of the cuboid in X, Y, Z direction.
This is mostly useful for brushes since it allows commands such as `//replace` to be ran, but it can also be used standalone.
//cubeapply 10 replaceinverse air default:water_source
//brush cubeapply 15 drain
//brush cubeapply 12 3 12 drain
//brush cubeapply 1 deleteblocks

View File

@ -46,6 +46,9 @@ end
function worldedit.keep_loaded(pos1, pos2)
-- Create a vmanip and read the area from map, this
-- causes all MapBlocks to be loaded into memory.
-- This doesn't actually *keep* them loaded, unlike the name implies.
local manip = minetest.get_voxel_manip()
manip:read_from_map(pos1, pos2)
end

View File

@ -98,21 +98,6 @@ worldedit.marker_move = function(name, marker, deltavector)
return true
end
-- Updates the location ingame of the markers
worldedit.marker_update = function(name, marker)
if marker == nil then
worldedit.mark_pos1(name)
worldedit.mark_pos2(name)
elseif marker == 1 then
worldedit.mark_pos1(name)
elseif marker == 2 then
worldedit.mark_pos2(name)
else
minetest.debug(
"worldedit: Invalid execution of function update_markers")
end
end
-- Returns two vectors with the directions for volumetric expansion
worldedit.get_expansion_directions = function(mark1, mark2)

View File

@ -114,16 +114,44 @@ function worldedit.serialize(pos1, pos2)
return LATEST_SERIALIZATION_HEADER .. result, count
end
--- Loads the schematic in `value` into a node list in the latest format.
-- Contains code based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile)
-- by ChillCode, available under the MIT license.
local function deserialize_workaround(content)
local nodes
if not jit then
nodes = minetest.deserialize(content, true)
else
-- XXX: This is a filthy hack that works surprisingly well
-- in LuaJIT, `minetest.deserialize` will fail due to the register limit
nodes = {}
content = content:gsub("^%s*return%s*{", "", 1):gsub("}%s*$", "", 1) -- remove the starting and ending values to leave only the node data
-- remove string contents strings while preserving their length
local escaped = content:gsub("\\\\", "@@"):gsub("\\\"", "@@"):gsub("(\"[^\"]*\")", function(s) return string.rep("@", #s) end)
local startpos, startpos1 = 1, 1
local endpos
while true do -- go through each individual node entry (except the last)
startpos, endpos = escaped:find("},%s*{", startpos)
if not startpos then
break
end
local current = content:sub(startpos1, startpos)
local entry = minetest.deserialize("return " .. current, true)
table.insert(nodes, entry)
startpos, startpos1 = endpos, endpos
end
local entry = minetest.deserialize("return " .. content:sub(startpos1), true) -- process the last entry
table.insert(nodes, entry)
end
return nodes
end
--- Loads the schematic in `value` into a node list in the latest format.
-- @return A node list in the latest format, or nil on failure.
local function load_schematic(value)
local version, header, content = worldedit.read_header(value)
local nodes = {}
if version == 1 or version == 2 then -- Original flat table format
local tables = minetest.deserialize(content)
local tables = minetest.deserialize(content, true)
if not tables then return nil end
-- Transform the node table into an array of nodes
@ -161,28 +189,7 @@ local function load_schematic(value)
})
end
elseif version == 4 or version == 5 then -- Nested table format
if not jit then
-- This is broken for larger tables in the current version of LuaJIT
nodes = minetest.deserialize(content)
else
-- XXX: This is a filthy hack that works surprisingly well - in LuaJIT, `minetest.deserialize` will fail due to the register limit
nodes = {}
content = content:gsub("return%s*{", "", 1):gsub("}%s*$", "", 1) -- remove the starting and ending values to leave only the node data
local escaped = content:gsub("\\\\", "@@"):gsub("\\\"", "@@"):gsub("(\"[^\"]*\")", function(s) return string.rep("@", #s) end)
local startpos, startpos1, endpos = 1, 1
while true do -- go through each individual node entry (except the last)
startpos, endpos = escaped:find("},%s*{", startpos)
if not startpos then
break
end
local current = content:sub(startpos1, startpos)
local entry = minetest.deserialize("return " .. current)
table.insert(nodes, entry)
startpos, startpos1 = endpos, endpos
end
local entry = minetest.deserialize("return " .. content:sub(startpos1)) -- process the last entry
table.insert(nodes, entry)
end
nodes = deserialize_workaround(content)
else
return nil
end

View File

@ -39,7 +39,7 @@ local brush_on_use = function(itemstack, placer)
assert(pointed_thing.type == "node")
worldedit.pos1[name] = pointed_thing.under
worldedit.pos2[name] = nil
worldedit.mark_region(name)
worldedit.marker_update(name)
-- this isn't really clean...
local player_notify_old = worldedit.player_notify
@ -101,7 +101,7 @@ worldedit.register_command("brush", {
else
local cmddef = worldedit.registered_commands[cmd]
if cmddef == nil or cmddef.require_pos ~= 1 then
worldedit.player_notify(name, "Invalid command for brush use: //" .. cmd)
worldedit.player_notify(name, "//" .. cmd .. " cannot be used with brushes")
return
end
@ -109,7 +109,7 @@ worldedit.register_command("brush", {
local ok, err = cmddef.parse(params)
if not ok then
err = err or "invalid usage"
worldedit.player_notify(name, "Brush command: " .. err)
worldedit.player_notify(name, "Error with brush command: " .. err)
return
end

View File

@ -1,5 +1,5 @@
worldedit.register_command("outset", {
params = "[h|v] <amount>",
params = "[h/v] <amount>",
description = "Outset the selected region.",
privs = {worldedit=true},
require_pos = 2,
@ -38,7 +38,7 @@ worldedit.register_command("outset", {
worldedit.register_command("inset", {
params = "[h|v] <amount>",
params = "[h/v] <amount>",
description = "Inset the selected region.",
privs = {worldedit=true},
require_pos = 2,
@ -47,9 +47,7 @@ worldedit.register_command("inset", {
if find == nil then
return false
end
local hv_test = dir:find("[^hv]+")
if hv_test ~= nil then
if dir:find("[^hv]") ~= nil then
return false, "Invalid direction."
end
@ -77,8 +75,8 @@ worldedit.register_command("inset", {
worldedit.register_command("shift", {
params = "[x|y|z|?|up|down|left|right|front|back] [+|-]<amount>",
description = "Moves the selection region. Does not move contents.",
params = "x/y/z/?/up/down/left/right/front/back [+/-]<amount>",
description = "Shifts the selection area without moving its contents",
privs = {worldedit=true},
require_pos = 2,
parse = function(param)
@ -112,8 +110,8 @@ worldedit.register_command("shift", {
worldedit.register_command("expand", {
params = "[+|-]<x|y|z|?|up|down|left|right|front|back> <amount> [reverse-amount]",
description = "expand the selection in one or two directions at once",
params = "[+/-]x/y/z/?/up/down/left/right/front/back <amount> [reverse amount]",
description = "Expands the selection in the selected absolute or relative axis",
privs = {worldedit=true},
require_pos = 2,
parse = function(param)
@ -161,8 +159,8 @@ worldedit.register_command("expand", {
worldedit.register_command("contract", {
params = "[+|-]<x|y|z|?|up|down|left|right|front|back> <amount> [reverse-amount]",
description = "contract the selection in one or two directions at once",
params = "[+/-]x/y/z/?/up/down/left/right/front/back <amount> [reverse amount]",
description = "Contracts the selection in the selected absolute or relative axis",
privs = {worldedit=true},
require_pos = 2,
parse = function(param)
@ -207,3 +205,62 @@ worldedit.register_command("contract", {
return true, "Region contracted by " .. (amount + rev_amount) .. " nodes"
end,
})
worldedit.register_command("cubeapply", {
params = "<size>/(<sizex> <sizey> <sizez>) <command> [parameters]",
description = "Select a cube with side length <size> around position 1 and run <command> on region",
privs = {worldedit=true},
require_pos = 1,
parse = function(param)
local found, _, sidex, sidey, sidez, cmd, args =
param:find("^(%d+)%s+(%d+)%s+(%d+)%s+([^%s]+)%s*(.*)$")
if found == nil then
found, _, sidex, cmd, args = param:find("^(%d+)%s+([^%s]+)%s*(.*)$")
if found == nil then
return false
end
sidey = sidex
sidez = sidex
end
sidex = tonumber(sidex)
sidey = tonumber(sidey)
sidez = tonumber(sidez)
if sidex < 1 or sidey < 1 or sidez < 1 then
return false
end
local cmddef = worldedit.registered_commands[cmd]
if cmddef == nil or cmddef.require_pos ~= 2 then
return false, "invalid usage: //" .. cmd .. " cannot be used with cubeapply"
end
-- run parsing of target command
local parsed = {cmddef.parse(args)}
if not table.remove(parsed, 1) then
return false, parsed[1]
end
return true, sidex, sidey, sidez, cmd, parsed
end,
nodes_needed = function(name, sidex, sidey, sidez, cmd, parsed)
-- its not possible to defer to the target command at this point
return sidex * sidey * sidez
end,
func = function(name, sidex, sidey, sidez, cmd, parsed)
local cmddef = assert(worldedit.registered_commands[cmd])
local success, missing_privs = minetest.check_player_privs(name, cmddef.privs)
if not success then
worldedit.player_notify(name, "Missing privileges: " ..
table.concat(missing_privs, ", "))
return
end
-- update region to be the cuboid the user wanted
local half = vector.divide(vector.new(sidex, sidey, sidez), 2)
local sizea, sizeb = vector.apply(half, math.floor), vector.apply(half, math.ceil)
local center = worldedit.pos1[name]
worldedit.pos1[name] = vector.subtract(center, sizea)
worldedit.pos2[name] = vector.add(center, vector.subtract(sizeb, 1))
worldedit.marker_update(name)
-- actually run target command
return cmddef.func(name, unpack(parsed))
end,
})

View File

@ -122,8 +122,9 @@ local function check_region(name)
return worldedit.volume(worldedit.pos1[name], worldedit.pos2[name])
end
-- Strips any kind of escape codes (translation, colors) from a string
-- https://github.com/minetest/minetest/blob/53dd7819277c53954d1298dfffa5287c306db8d0/src/util/string.cpp#L777
local function strip_translation_escapes(input)
local function strip_escapes(input)
local s = function(idx) return input:sub(idx, idx) end
local out = ""
local i = 1
@ -153,6 +154,8 @@ local function string_endswith(full, part)
return full:find(part, 1, true) == #full - #part + 1
end
local description_cache = nil
-- normalizes node "description" `nodename`, returning a string (or nil)
worldedit.normalize_nodename = function(nodename)
nodename = nodename:gsub("^%s*(.-)%s*$", "%1") -- strip spaces
@ -163,16 +166,30 @@ worldedit.normalize_nodename = function(nodename)
return fullname
end
nodename = nodename:lower()
for key, value in pairs(minetest.registered_nodes) do
if string_endswith(key, ":" .. nodename) then -- matches name (w/o mod part)
for key, _ in pairs(minetest.registered_nodes) do
if string_endswith(key:lower(), ":" .. nodename) then -- matches name (w/o mod part)
return key
end
end
for key, value in pairs(minetest.registered_nodes) do
local desc = strip_translation_escapes(value.description):lower()
if description_cache == nil then
-- cache stripped descriptions
description_cache = {}
for key, value in pairs(minetest.registered_nodes) do
local desc = strip_escapes(value.description):gsub("\n.*", "", 1):lower()
if desc ~= "" then
description_cache[key] = desc
end
end
end
for key, desc in pairs(description_cache) do
if desc == nodename then -- matches description
return key
end
end
for key, desc in pairs(description_cache) do
if desc == nodename .. " block" then
-- fuzzy description match (e.g. "Steel" == "Steel Block")
return key
@ -180,8 +197,8 @@ worldedit.normalize_nodename = function(nodename)
end
local match = nil
for key, value in pairs(minetest.registered_nodes) do
if value.description:lower():find(nodename, 1, true) ~= nil then
for key, value in pairs(description_cache) do
if value:find(nodename, 1, true) ~= nil then
if match ~= nil then
return nil
end
@ -215,7 +232,10 @@ worldedit.register_command("about", {
params = "",
description = "Get information about the WorldEdit mod",
func = function(name)
worldedit.player_notify(name, "WorldEdit " .. worldedit.version_string .. " is available on this server. Type //help to get a list of commands, or get more information at https://github.com/Uberi/Minetest-WorldEdit")
worldedit.player_notify(name, "WorldEdit " .. worldedit.version_string..
" is available on this server. Type //help to get a list of "..
"commands, or get more information at "..
"https://github.com/Uberi/Minetest-WorldEdit")
end,
})
@ -332,8 +352,7 @@ worldedit.register_command("reset", {
func = function(name)
worldedit.pos1[name] = nil
worldedit.pos2[name] = nil
worldedit.mark_pos1(name)
worldedit.mark_pos2(name)
worldedit.marker_update(name)
worldedit.set_pos[name] = nil
--make sure the user does not try to confirm an operation after resetting pos:
reset_pending(name)
@ -346,8 +365,7 @@ worldedit.register_command("mark", {
description = "Show markers at the region positions",
privs = {worldedit=true},
func = function(name)
worldedit.mark_pos1(name)
worldedit.mark_pos2(name)
worldedit.marker_update(name)
worldedit.player_notify(name, "region marked")
end,
})
@ -360,8 +378,7 @@ worldedit.register_command("unmark", {
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
worldedit.pos1[name] = nil
worldedit.pos2[name] = nil
worldedit.mark_pos1(name)
worldedit.mark_pos2(name)
worldedit.marker_update(name)
worldedit.pos1[name] = pos1
worldedit.pos2[name] = pos2
worldedit.player_notify(name, "region unmarked")
@ -430,7 +447,7 @@ worldedit.register_command("p", {
})
worldedit.register_command("fixedpos", {
params = "set1/set2 x y z",
params = "set1/set2 <x> <y> <z>",
description = "Set a WorldEdit region position to the position at (<x>, <y>, <z>)",
privs = {worldedit=true},
parse = function(param)
@ -539,7 +556,7 @@ worldedit.register_command("param2", {
parse = function(param)
local param2 = tonumber(param)
if not param2 then
return false, "Invalid or missing param2 argument"
return false
elseif param2 < 0 or param2 > 255 then
return false, "Param2 is out of range (must be between 0 and 255 inclusive!)"
end
@ -553,7 +570,7 @@ worldedit.register_command("param2", {
})
worldedit.register_command("mix", {
params = "<node1> [<weighting1>] [<node2> [<weighting2>]] ...",
params = "<node1> [count1] <node2> [count2] ...",
description = "Fill the current WorldEdit region with a random mix of <node1>, ...",
privs = {worldedit=true},
require_pos = 2,
@ -573,6 +590,9 @@ worldedit.register_command("mix", {
nodes[#nodes + 1] = node
end
end
if #nodes == 0 then
return false
end
return true, nodes
end,
nodes_needed = check_region,
@ -773,7 +793,7 @@ end
worldedit.register_command("hollowcylinder", {
params = "x/y/z/? <length> <radius1> [radius2] <node>",
description = "Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>",
description = "Add hollow cylinder at WorldEdit position 1 along the given axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>",
privs = {worldedit=true},
require_pos = 1,
parse = check_cylinder,
@ -794,7 +814,7 @@ worldedit.register_command("hollowcylinder", {
worldedit.register_command("cylinder", {
params = "x/y/z/? <length> <radius1> [radius2] <node>",
description = "Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>",
description = "Add cylinder at WorldEdit position 1 along the given axis with length <length>, base radius <radius1> (and top radius [radius2]), composed of <node>",
privs = {worldedit=true},
require_pos = 1,
parse = check_cylinder,
@ -827,7 +847,7 @@ end
worldedit.register_command("hollowpyramid", {
params = "x/y/z/? <height> <node>",
description = "Add hollow pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height <height>, composed of <node>",
description = "Add hollow pyramid centered at WorldEdit position 1 along the given axis with height <height>, composed of <node>",
privs = {worldedit=true},
require_pos = 1,
parse = check_pyramid,
@ -847,7 +867,7 @@ worldedit.register_command("hollowpyramid", {
worldedit.register_command("pyramid", {
params = "x/y/z/? <height> <node>",
description = "Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height <height>, composed of <node>",
description = "Add pyramid centered at WorldEdit position 1 along the given axis with height <height>, composed of <node>",
privs = {worldedit=true},
require_pos = 1,
parse = check_pyramid,
@ -892,7 +912,7 @@ worldedit.register_command("spiral", {
worldedit.register_command("copy", {
params = "x/y/z/? <amount>",
description = "Copy the current WorldEdit region along the x/y/z/? axis by <amount> nodes",
description = "Copy the current WorldEdit region along the given axis by <amount> nodes",
privs = {worldedit=true},
require_pos = 2,
parse = function(param)
@ -919,7 +939,7 @@ worldedit.register_command("copy", {
worldedit.register_command("move", {
params = "x/y/z/? <amount>",
description = "Move the current WorldEdit region along the x/y/z/? axis by <amount> nodes",
description = "Move the current WorldEdit region along the given axis by <amount> nodes",
privs = {worldedit=true},
require_pos = 2,
parse = function(param)
@ -944,15 +964,14 @@ worldedit.register_command("move", {
pos1[axis] = pos1[axis] + amount
pos2[axis] = pos2[axis] + amount
worldedit.mark_pos1(name)
worldedit.mark_pos2(name)
worldedit.marker_update(name)
worldedit.player_notify(name, count .. " nodes moved")
end,
})
worldedit.register_command("stack", {
params = "x/y/z/? <count>",
description = "Stack the current WorldEdit region along the x/y/z/? axis <count> times",
description = "Stack the current WorldEdit region along the given axis <count> times",
privs = {worldedit=true},
require_pos = 2,
parse = function(param)
@ -1036,8 +1055,7 @@ worldedit.register_command("stretch", {
--reset markers to scaled positions
worldedit.pos1[name] = pos1
worldedit.pos2[name] = pos2
worldedit.mark_pos1(name)
worldedit.mark_pos2(name)
worldedit.marker_update(name)
worldedit.player_notify(name, count .. " nodes stretched")
end,
@ -1045,7 +1063,7 @@ worldedit.register_command("stretch", {
worldedit.register_command("transpose", {
params = "x/y/z/? x/y/z/?",
description = "Transpose the current WorldEdit region along the x/y/z/? and x/y/z/? axes",
description = "Transpose the current WorldEdit region along the given axes",
privs = {worldedit=true},
require_pos = 2,
parse = function(param)
@ -1067,8 +1085,7 @@ worldedit.register_command("transpose", {
--reset markers to transposed positions
worldedit.pos1[name] = pos1
worldedit.pos2[name] = pos2
worldedit.mark_pos1(name)
worldedit.mark_pos2(name)
worldedit.marker_update(name)
worldedit.player_notify(name, count .. " nodes transposed")
end,
@ -1076,7 +1093,7 @@ worldedit.register_command("transpose", {
worldedit.register_command("flip", {
params = "x/y/z/?",
description = "Flip the current WorldEdit region along the x/y/z/? axis",
description = "Flip the current WorldEdit region along the given axis",
privs = {worldedit=true},
require_pos = 2,
parse = function(param)
@ -1094,8 +1111,8 @@ worldedit.register_command("flip", {
})
worldedit.register_command("rotate", {
params = "<axis> <angle>",
description = "Rotate the current WorldEdit region around the axis <axis> by angle <angle> (90 degree increment)",
params = "x/y/z/? <angle>",
description = "Rotate the current WorldEdit region around the given axis by angle <angle> (90 degree increment)",
privs = {worldedit=true},
require_pos = 2,
parse = function(param)
@ -1118,8 +1135,7 @@ worldedit.register_command("rotate", {
--reset markers to rotated positions
worldedit.pos1[name] = pos1
worldedit.pos2[name] = pos2
worldedit.mark_pos1(name)
worldedit.mark_pos2(name)
worldedit.marker_update(name)
worldedit.player_notify(name, count .. " nodes rotated")
end,
@ -1186,6 +1202,85 @@ worldedit.register_command("drain", {
end,
})
local clearcut_cache
local function clearcut(pos1, pos2)
-- decide which nodes we consider plants
if clearcut_cache == nil then
clearcut_cache = {}
for name, def in pairs(minetest.registered_nodes) do
local groups = def.groups or {}
if (
-- the groups say so
groups.flower or groups.grass or groups.flora or groups.plant or
groups.leaves or groups.tree or groups.leafdecay or groups.sapling or
-- drawtype heuristic
(def.is_ground_content and def.buildable_to and
(def.sunlight_propagates or not def.walkable)
and def.drawtype == "plantlike") or
-- if it's flammable, it probably needs to go too
(def.is_ground_content and not def.walkable and groups.flammable)
) then
clearcut_cache[name] = true
end
end
end
local plants = clearcut_cache
local count = 0
local prev, any
for x = pos1.x, pos2.x do
for z = pos1.z, pos2.z do
prev = false
any = false
-- first pass: remove floating nodes that would be left over
for y = pos1.y, pos2.y do
local n = minetest.get_node({x=x, y=y, z=z}).name
if plants[n] then
prev = true
any = true
elseif prev then
local def = minetest.registered_nodes[n] or {}
local groups = def.groups or {}
if groups.attached_node or (def.buildable_to and groups.falling_node) then
minetest.remove_node({x=x, y=y, z=z})
count = count + 1
else
prev = false
end
end
end
-- second pass: remove plants, top-to-bottom to avoid item drops
if any then
for y = pos2.y, pos1.y, -1 do
local n = minetest.get_node({x=x, y=y, z=z}).name
if plants[n] then
minetest.remove_node({x=x, y=y, z=z})
count = count + 1
end
end
end
end
end
return count
end
worldedit.register_command("clearcut", {
params = "",
description = "Remove any plant, tree or foilage-like nodes in the selected region",
privs = {worldedit=true},
require_pos = 2,
nodes_needed = check_region,
func = function(name)
local pos1, pos2 = worldedit.sort_pos(worldedit.pos1[name], worldedit.pos2[name])
local count = clearcut(pos1, pos2)
worldedit.player_notify(name, count .. " nodes removed")
end,
})
worldedit.register_command("hide", {
params = "",
description = "Hide all nodes in the current WorldEdit region non-destructively",
@ -1345,9 +1440,8 @@ worldedit.register_command("allocate", {
end
worldedit.pos1[name] = nodepos1
worldedit.mark_pos1(name)
worldedit.pos2[name] = nodepos2
worldedit.mark_pos2(name)
worldedit.marker_update(name)
worldedit.player_notify(name, count .. " nodes allocated")
end,

View File

@ -2,57 +2,60 @@ worldedit.marker1 = {}
worldedit.marker2 = {}
worldedit.marker_region = {}
local init_sentinel = "new" .. tostring(math.random(99999))
--marks worldedit region position 1
worldedit.mark_pos1 = function(name)
worldedit.mark_pos1 = function(name, region_too)
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
if pos1 ~= nil then
--make area stay loaded
local manip = minetest.get_voxel_manip()
manip:read_from_map(pos1, pos1)
end
if worldedit.marker1[name] ~= nil then --marker already exists
worldedit.marker1[name]:remove() --remove marker
worldedit.marker1[name] = nil
end
if pos1 ~= nil then
--make area stay loaded
local manip = minetest.get_voxel_manip()
manip:read_from_map(pos1, pos1)
--add marker
worldedit.marker1[name] = minetest.add_entity(pos1, "worldedit:pos1")
worldedit.marker1[name] = minetest.add_entity(pos1, "worldedit:pos1", init_sentinel)
if worldedit.marker1[name] ~= nil then
worldedit.marker1[name]:get_luaentity().player_name = name
end
end
worldedit.mark_region(name)
if region_too == nil or region_too then
worldedit.mark_region(name)
end
end
--marks worldedit region position 2
worldedit.mark_pos2 = function(name)
worldedit.mark_pos2 = function(name, region_too)
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
if pos2 ~= nil then
--make area stay loaded
local manip = minetest.get_voxel_manip()
manip:read_from_map(pos2, pos2)
end
if worldedit.marker2[name] ~= nil then --marker already exists
worldedit.marker2[name]:remove() --remove marker
worldedit.marker2[name] = nil
end
if pos2 ~= nil then
--make area stay loaded
local manip = minetest.get_voxel_manip()
manip:read_from_map(pos2, pos2)
--add marker
worldedit.marker2[name] = minetest.add_entity(pos2, "worldedit:pos2")
worldedit.marker2[name] = minetest.add_entity(pos2, "worldedit:pos2", init_sentinel)
if worldedit.marker2[name] ~= nil then
worldedit.marker2[name]:get_luaentity().player_name = name
end
end
worldedit.mark_region(name)
if region_too == nil or region_too then
worldedit.mark_region(name)
end
end
worldedit.mark_region = function(name)
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
if worldedit.marker_region[name] ~= nil then --marker already exists
--wip: make the area stay loaded somehow
for _, entity in ipairs(worldedit.marker_region[name]) do
entity:remove()
end
@ -82,7 +85,8 @@ worldedit.mark_region = function(name)
--XY plane markers
for _, z in ipairs({pos1.z - 0.5, pos2.z + 0.5}) do
local marker = minetest.add_entity({x=pos1.x + sizex - 0.5, y=pos1.y + sizey - 0.5, z=z}, "worldedit:region_cube")
local entpos = {x=pos1.x + sizex - 0.5, y=pos1.y + sizey - 0.5, z=z}
local marker = minetest.add_entity(entpos, "worldedit:region_cube", init_sentinel)
if marker ~= nil then
marker:set_properties({
visual_size={x=sizex * 2, y=sizey * 2},
@ -95,7 +99,8 @@ worldedit.mark_region = function(name)
--YZ plane markers
for _, x in ipairs({pos1.x - 0.5, pos2.x + 0.5}) do
local marker = minetest.add_entity({x=x, y=pos1.y + sizey - 0.5, z=pos1.z + sizez - 0.5}, "worldedit:region_cube")
local entpos = {x=x, y=pos1.y + sizey - 0.5, z=pos1.z + sizez - 0.5}
local marker = minetest.add_entity(entpos, "worldedit:region_cube", init_sentinel)
if marker ~= nil then
marker:set_properties({
visual_size={x=sizez * 2, y=sizey * 2},
@ -111,6 +116,13 @@ worldedit.mark_region = function(name)
end
end
--convenience function that calls everything
worldedit.marker_update = function(name)
worldedit.mark_pos1(name, false)
worldedit.mark_pos2(name, false)
worldedit.mark_region(name)
end
minetest.register_entity(":worldedit:pos1", {
initial_properties = {
visual = "cube",
@ -120,9 +132,11 @@ minetest.register_entity(":worldedit:pos1", {
"worldedit_pos1.png", "worldedit_pos1.png"},
collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
physical = false,
static_save = false,
},
on_step = function(self, dtime)
if worldedit.marker1[self.player_name] == nil then
on_activate = function(self, staticdata, dtime_s)
if staticdata ~= init_sentinel then
-- we were loaded from before static_save = false was added
self.object:remove()
end
end,
@ -130,6 +144,9 @@ minetest.register_entity(":worldedit:pos1", {
self.object:remove()
worldedit.marker1[self.player_name] = nil
end,
on_blast = function(self, damage)
return false, false, {} -- don't damage or knockback
end,
})
minetest.register_entity(":worldedit:pos2", {
@ -141,9 +158,11 @@ minetest.register_entity(":worldedit:pos2", {
"worldedit_pos2.png", "worldedit_pos2.png"},
collisionbox = {-0.55, -0.55, -0.55, 0.55, 0.55, 0.55},
physical = false,
static_save = false,
},
on_step = function(self, dtime)
if worldedit.marker2[self.player_name] == nil then
on_activate = function(self, staticdata, dtime_s)
if staticdata ~= init_sentinel then
-- we were loaded from before static_save = false was added
self.object:remove()
end
end,
@ -151,6 +170,9 @@ minetest.register_entity(":worldedit:pos2", {
self.object:remove()
worldedit.marker2[self.player_name] = nil
end,
on_blast = function(self, damage)
return false, false, {} -- don't damage or knockback
end,
})
minetest.register_entity(":worldedit:region_cube", {
@ -159,11 +181,12 @@ minetest.register_entity(":worldedit:region_cube", {
textures = {"worldedit_cube.png"},
visual_size = {x=10, y=10},
physical = false,
static_save = false,
},
on_step = function(self, dtime)
if worldedit.marker_region[self.player_name] == nil then
on_activate = function(self, staticdata, dtime_s)
if staticdata ~= init_sentinel then
-- we were loaded from before static_save = false was added
self.object:remove()
return
end
end,
on_punch = function(self, hitter)
@ -176,5 +199,8 @@ minetest.register_entity(":worldedit:region_cube", {
end
worldedit.marker_region[self.player_name] = nil
end,
on_blast = function(self, damage)
return false, false, {} -- don't damage or knockback
end,
})

View File

@ -132,11 +132,21 @@ local function handle_changes(name, identifier, fields, def)
return true
end
-- This has the same behaviour as the player invoking the chat command
local function execute_worldedit_command(command_name, player_name, params)
local chatcmd = minetest.registered_chatcommands["/" .. command_name]
assert(chatcmd, "unknown command: " .. command_name)
local _, msg = chatcmd.func(player_name, params)
if msg then
worldedit.player_notify(player_name, msg)
end
end
worldedit.register_gui_function("worldedit_gui_about", {
name = "About",
privs = {interact=true},
on_select = function(name)
minetest.chatcommands["/about"].func(name, "")
execute_worldedit_command("about", name, "")
end,
})
@ -144,7 +154,8 @@ worldedit.register_gui_function("worldedit_gui_inspect", {
name = "Toggle Inspect",
privs = we_privs("inspect"),
on_select = function(name)
minetest.chatcommands["/inspect"].func(name, worldedit.inspect[name] and "disable" or "enable")
execute_worldedit_command("inspect", name,
worldedit.inspect[name] and "disable" or "enable")
end,
})
@ -178,47 +189,47 @@ worldedit.register_gui_function("worldedit_gui_region", {
worldedit.register_gui_handler("worldedit_gui_region", function(name, fields)
if fields.worldedit_gui_p_get then
minetest.chatcommands["/p"].func(name, "get")
execute_worldedit_command("p", name, "get")
return true
elseif fields.worldedit_gui_p_set1 then
minetest.chatcommands["/p"].func(name, "set1")
execute_worldedit_command("p", name, "set1")
return true
elseif fields.worldedit_gui_p_set2 then
minetest.chatcommands["/p"].func(name, "set2")
execute_worldedit_command("p", name, "set2")
return true
elseif fields.worldedit_gui_pos1 then
minetest.chatcommands["/pos1"].func(name, "")
execute_worldedit_command("pos1", name, "")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_pos2 then
minetest.chatcommands["/pos2"].func(name, "")
execute_worldedit_command("pos2", name, "")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_reset then
minetest.chatcommands["/reset"].func(name, "")
execute_worldedit_command("reset", name, "")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_mark then
minetest.chatcommands["/mark"].func(name, "")
execute_worldedit_command("mark", name, "")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_unmark then
minetest.chatcommands["/unmark"].func(name, "")
execute_worldedit_command("unmark", name, "")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_volume then
minetest.chatcommands["/volume"].func(name, "")
execute_worldedit_command("volume", name, "")
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_fixedpos_pos1_submit then
minetest.chatcommands["/fixedpos"].func(name, string.format("set1 %s %s %s",
execute_worldedit_command("fixedpos", name, ("set1 %s %s %s"):format(
tostring(fields.worldedit_gui_fixedpos_pos1x),
tostring(fields.worldedit_gui_fixedpos_pos1y),
tostring(fields.worldedit_gui_fixedpos_pos1z)))
worldedit.show_page(name, "worldedit_gui_region")
return true
elseif fields.worldedit_gui_fixedpos_pos2_submit then
minetest.chatcommands["/fixedpos"].func(name, string.format("set2 %s %s %s",
execute_worldedit_command("fixedpos", name, ("set2 %s %s %s"):format(
tostring(fields.worldedit_gui_fixedpos_pos2x),
tostring(fields.worldedit_gui_fixedpos_pos2y),
tostring(fields.worldedit_gui_fixedpos_pos2z)))
@ -255,7 +266,7 @@ worldedit.register_gui_handler("worldedit_gui_set", function(name, fields)
local n = worldedit.normalize_nodename(gui_nodename1[name])
if n then
minetest.chatcommands["/set"].func(name, n)
execute_worldedit_command("set", name, n)
end
return true
end
@ -301,7 +312,7 @@ worldedit.register_gui_handler("worldedit_gui_replace", function(name, fields)
local n1 = worldedit.normalize_nodename(gui_nodename1[name])
local n2 = worldedit.normalize_nodename(gui_nodename2[name])
if n1 and n2 then
minetest.chatcommands["/"..submit].func(name, string.format("%s %s", n1, n2))
execute_worldedit_command(submit, name, n1 .. " " .. n2)
end
return true
end
@ -350,7 +361,8 @@ worldedit.register_gui_handler("worldedit_gui_sphere_dome", function(name, field
end
local n = worldedit.normalize_nodename(gui_nodename1[name])
if n then
minetest.chatcommands["/"..submit].func(name, string.format("%s %s", gui_distance2[name], n))
execute_worldedit_command(submit, name,
gui_distance2[name] .. " " .. n)
end
return true
end
@ -404,7 +416,7 @@ worldedit.register_gui_handler("worldedit_gui_cylinder", function(name, fields)
local n = worldedit.normalize_nodename(gui_nodename1[name])
if n then
local args = string.format("%s %s %s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_distance2[name], gui_distance3[name], n)
minetest.chatcommands["/"..submit].func(name, args)
execute_worldedit_command(submit, name, args)
end
return true
end
@ -448,7 +460,9 @@ worldedit.register_gui_handler("worldedit_gui_pyramid", function(name, fields)
end
local n = worldedit.normalize_nodename(gui_nodename1[name])
if n then
minetest.chatcommands["/"..submit].func(name, string.format("%s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], n))
execute_worldedit_command(submit, name,
string.format("%s %s %s", axis_values[gui_axis1[name]],
gui_distance1[name], n))
end
return true
end
@ -491,7 +505,9 @@ worldedit.register_gui_handler("worldedit_gui_spiral", function(name, fields)
local n = worldedit.normalize_nodename(gui_nodename1[name])
if n then
minetest.chatcommands["/spiral"].func(name, string.format("%s %s %s %s", gui_distance1[name], gui_distance2[name], gui_distance3[name], n))
execute_worldedit_command("spiral", name,
string.format("%s %s %s %s", gui_distance1[name],
gui_distance2[name], gui_distance3[name], n))
end
return true
end
@ -527,7 +543,8 @@ worldedit.register_gui_handler("worldedit_gui_copy_move", function(name, fields)
if fields.worldedit_gui_copy_move_move then
submit = "move"
end
minetest.chatcommands["/"..submit].func(name, string.format("%s %s", axis_values[gui_axis1[name]], gui_distance1[name]))
execute_worldedit_command(submit, name,
axis_values[gui_axis1[name]] .. " " .. gui_distance1[name])
return true
end
return ret
@ -556,7 +573,8 @@ worldedit.register_gui_handler("worldedit_gui_stack", function(name, fields)
copy_changes(name, fields, cg)
worldedit.show_page(name, "worldedit_gui_stack")
minetest.chatcommands["/stack"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], gui_count1[name]))
execute_worldedit_command("stack", name,
axis_values[gui_axis1[name]] .. " " .. gui_count1[name])
return true
end
return ret
@ -589,7 +607,8 @@ worldedit.register_gui_handler("worldedit_gui_stretch", function(name, fields)
copy_changes(name, fields, cg)
worldedit.show_page(name, "worldedit_gui_stretch")
minetest.chatcommands["/stretch"].func(name, string.format("%s %s %s", gui_count1[name], gui_count2[name], gui_count3[name]))
execute_worldedit_command("stretch", name, string.format("%s %s %s",
gui_count1[name], gui_count2[name], gui_count3[name]))
return true
end
return ret
@ -616,7 +635,8 @@ worldedit.register_gui_handler("worldedit_gui_transpose", function(name, fields)
if fields.worldedit_gui_transpose_submit then
copy_changes(name, fields, cg)
minetest.chatcommands["/transpose"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], axis_values[gui_axis2[name]]))
execute_worldedit_command("transpose", name,
axis_values[gui_axis1[name]] .. " " .. axis_values[gui_axis2[name]])
return true
end
return ret
@ -642,7 +662,7 @@ worldedit.register_gui_handler("worldedit_gui_flip", function(name, fields)
copy_changes(name, fields, cg)
worldedit.show_page(name, "worldedit_gui_flip")
minetest.chatcommands["/flip"].func(name, axis_values[gui_axis1[name]])
execute_worldedit_command("flip", name, axis_values[gui_axis1[name]])
return true
end
return ret
@ -670,7 +690,8 @@ worldedit.register_gui_handler("worldedit_gui_rotate", function(name, fields)
copy_changes(name, fields, cg)
worldedit.show_page(name, "worldedit_gui_rotate")
minetest.chatcommands["/rotate"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], angle_values[gui_angle[name]]))
execute_worldedit_command("rotate", name,
axis_values[gui_axis1[name]] .. " " .. angle_values[gui_angle[name]])
return true
end
return ret
@ -696,7 +717,8 @@ worldedit.register_gui_handler("worldedit_gui_orient", function(name, fields)
copy_changes(name, fields, cg)
worldedit.show_page(name, "worldedit_gui_orient")
minetest.chatcommands["/orient"].func(name, tostring(angle_values[gui_angle[name]]))
execute_worldedit_command("orient", name,
tostring(angle_values[gui_angle[name]]))
return true
end
return ret
@ -706,7 +728,7 @@ worldedit.register_gui_function("worldedit_gui_fixlight", {
name = "Fix Lighting",
privs = we_privs("fixlight"),
on_select = function(name)
minetest.chatcommands["/fixlight"].func(name, "")
execute_worldedit_command("fixlight", name, "")
end,
})
@ -714,7 +736,7 @@ worldedit.register_gui_function("worldedit_gui_hide", {
name = "Hide Region",
privs = we_privs("hide"),
on_select = function(name)
minetest.chatcommands["/hide"].func(name, "")
execute_worldedit_command("hide", name, "")
end,
})
@ -745,7 +767,7 @@ worldedit.register_gui_handler("worldedit_gui_suppress", function(name, fields)
local n = worldedit.normalize_nodename(gui_nodename1[name])
if n then
minetest.chatcommands["/suppress"].func(name, n)
execute_worldedit_command("suppress", name, n)
end
return true
end
@ -779,7 +801,7 @@ worldedit.register_gui_handler("worldedit_gui_highlight", function(name, fields)
local n = worldedit.normalize_nodename(gui_nodename1[name])
if n then
minetest.chatcommands["/highlight"].func(name, n)
execute_worldedit_command("highlight", name, n)
end
return true
end
@ -790,7 +812,7 @@ worldedit.register_gui_function("worldedit_gui_restore", {
name = "Restore Region",
privs = we_privs("restore"),
on_select = function(name)
minetest.chatcommands["/restore"].func(name, "")
execute_worldedit_command("restore", name, "")
end,
})
@ -814,11 +836,11 @@ worldedit.register_gui_handler("worldedit_gui_save_load", function(name, fields)
worldedit.show_page(name, "worldedit_gui_save_load")
if fields.worldedit_gui_save_load_submit_save then
minetest.chatcommands["/save"].func(name, gui_filename[name])
execute_worldedit_command("save", name, gui_filename[name])
elseif fields.worldedit_gui_save_load_submit_allocate then
minetest.chatcommands["/allocate"].func(name, gui_filename[name])
execute_worldedit_command("allocate", name, gui_filename[name])
else --fields.worldedit_gui_save_load_submit_load
minetest.chatcommands["/load"].func(name, gui_filename[name])
execute_worldedit_command("load", name, gui_filename[name])
end
return true
end
@ -868,7 +890,7 @@ worldedit.register_gui_handler("worldedit_gui_cube", function(name, fields)
local n = worldedit.normalize_nodename(gui_nodename1[name])
if n then
local args = string.format("%s %s %s %s", gui_distance1[name], gui_distance2[name], gui_distance3[name], n)
minetest.chatcommands["/"..submit].func(name, args)
execute_worldedit_command(submit, name, args)
end
return true
end
@ -879,6 +901,6 @@ worldedit.register_gui_function("worldedit_gui_clearobjects", {
name = "Clear Objects",
privs = we_privs("clearobjects"),
on_select = function(name)
minetest.chatcommands["/clearobjects"].func(name, "")
execute_worldedit_command("clearobjects", name, "")
end,
})