1 minetest.register_privilege("worldedit", "Can use WorldEdit commands")
\r
5 worldedit.set_pos = {}
\r
10 dofile(minetest.get_modpath("worldedit") .. "/functions.lua")
\r
11 dofile(minetest.get_modpath("worldedit") .. "/mark.lua")
\r
12 dofile(minetest.get_modpath("worldedit") .. "/table_save.lua")
\r
14 --determines whether `nodename` is a valid node name, returning a boolean
\r
15 worldedit.node_is_valid = function(temp_pos, nodename)
\r
16 return minetest.registered_nodes[nodename] ~= nil
\r
17 or minetest.registered_nodes["default:" .. nodename] ~= nil
\r
20 --determines the axis in which a player is facing, returning an axis ("x", "y", or "z") and the sign (1 or -1)
\r
21 worldedit.player_axis = function(name)
\r
22 local dir = minetest.env:get_player_by_name(name):get_look_dir()
\r
23 local x, y, z = math.abs(dir.x), math.abs(dir.y), math.abs(dir.z)
\r
26 return "x", dir.x > 0 and 1 or -1
\r
29 return "y", dir.y > 0 and 1 or -1
\r
31 return "z", dir.z > 0 and 1 or -1
\r
34 minetest.register_chatcommand("/reset", {
\r
36 description = "Reset the region so that it is empty",
\r
37 privs = {worldedit=true},
\r
38 func = function(name, param)
\r
39 worldedit.pos1[name] = nil
\r
40 worldedit.pos2[name] = nil
\r
41 worldedit.mark_pos1(name)
\r
42 worldedit.mark_pos2(name)
\r
43 minetest.chat_send_player(name, "WorldEdit region reset")
\r
47 minetest.register_chatcommand("/mark", {
\r
49 description = "Show markers at the region positions",
\r
50 privs = {worldedit=true},
\r
51 func = function(name, param)
\r
52 worldedit.mark_pos1(name)
\r
53 worldedit.mark_pos2(name)
\r
54 minetest.chat_send_player(name, "WorldEdit region marked")
\r
58 minetest.register_chatcommand("/pos1", {
\r
60 description = "Set WorldEdit region position 1 to the player's location",
\r
61 privs = {worldedit=true},
\r
62 func = function(name, param)
\r
63 local pos = minetest.env:get_player_by_name(name):getpos()
\r
64 pos.x, pos.y, pos.z = math.floor(pos.x), math.floor(pos.y), math.floor(pos.z)
\r
65 worldedit.pos1[name] = pos
\r
66 worldedit.mark_pos1(name)
\r
67 minetest.chat_send_player(name, "WorldEdit position 1 set to " .. minetest.pos_to_string(pos))
\r
71 minetest.register_chatcommand("/pos2", {
\r
73 description = "Set WorldEdit region position 2 to the player's location",
\r
74 privs = {worldedit=true},
\r
75 func = function(name, param)
\r
76 local pos = minetest.env:get_player_by_name(name):getpos()
\r
77 pos.x, pos.y, pos.z = math.floor(pos.x), math.floor(pos.y), math.floor(pos.z)
\r
78 worldedit.pos2[name] = pos
\r
79 worldedit.mark_pos2(name)
\r
80 minetest.chat_send_player(name, "WorldEdit position 2 set to " .. minetest.pos_to_string(pos))
\r
84 minetest.register_chatcommand("/p", {
\r
86 description = "Set WorldEdit region by punching two nodes, or display the current WorldEdit region",
\r
87 privs = {worldedit=true},
\r
88 func = function(name, param)
\r
89 if param == "set" then --set both WorldEdit positions
\r
90 worldedit.set_pos[name] = 1
\r
91 minetest.chat_send_player(name, "Select positions by punching two nodes")
\r
92 elseif param == "get" then --display current WorldEdit positions
\r
93 if worldedit.pos1[name] ~= nil then
\r
94 minetest.chat_send_player(name, "WorldEdit position 1: " .. minetest.pos_to_string(worldedit.pos1[name]))
\r
96 minetest.chat_send_player(name, "WorldEdit position 1 not set")
\r
98 if worldedit.pos2[name] ~= nil then
\r
99 minetest.chat_send_player(name, "WorldEdit position 2: " .. minetest.pos_to_string(worldedit.pos2[name]))
\r
101 minetest.chat_send_player(name, "WorldEdit position 2 not set")
\r
104 minetest.chat_send_player(name, "Unknown subcommand: " .. param)
\r
109 minetest.register_on_punchnode(function(pos, node, puncher)
\r
110 local name = puncher:get_player_name()
\r
111 if name ~= "" and worldedit.set_pos[name] ~= nil then --currently setting position
\r
112 if worldedit.set_pos[name] == 1 then --setting position 1
\r
113 worldedit.set_pos[name] = 2 --set position 2 on the next invocation
\r
114 worldedit.pos1[name] = pos
\r
115 worldedit.mark_pos1(name)
\r
116 minetest.chat_send_player(name, "WorldEdit region position 1 set to " .. minetest.pos_to_string(pos))
\r
117 else --setting position 2
\r
118 worldedit.set_pos[name] = nil --finished setting positions
\r
119 worldedit.pos2[name] = pos
\r
120 worldedit.mark_pos2(name)
\r
121 minetest.chat_send_player(name, "WorldEdit region position 2 set to " .. minetest.pos_to_string(pos))
\r
126 minetest.register_chatcommand("/volume", {
\r
128 description = "Display the volume of the current WorldEdit region",
\r
129 privs = {worldedit=true},
\r
130 func = function(name, param)
\r
131 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
132 if pos1 == nil or pos2 == nil then
\r
133 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
137 local volume = worldedit.volume(pos1, pos2)
\r
138 minetest.chat_send_player(name, "Current WorldEdit region has a volume of " .. volume .. " nodes (" .. pos2.x - pos1.x .. "*" .. pos2.y - pos1.y .. "*" .. pos2.z - pos1.z .. ")")
\r
142 minetest.register_chatcommand("/set", {
\r
144 description = "Set the current WorldEdit region to <node>",
\r
145 privs = {worldedit=true},
\r
146 func = function(name, param)
\r
147 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
148 if pos1 == nil or pos2 == nil then
\r
149 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
153 if param == "" or not worldedit.node_is_valid(pos1, param) then
\r
154 minetest.chat_send_player(name, "Invalid node name: " .. param)
\r
158 local count = worldedit.set(pos1, pos2, param)
\r
159 minetest.chat_send_player(name, count .. " nodes set")
\r
163 minetest.register_chatcommand("/replace", {
\r
164 params = "<search node> <replace node>",
\r
165 description = "Replace all instances of <search node> with <place node> in the current WorldEdit region",
\r
166 privs = {worldedit=true},
\r
167 func = function(name, param)
\r
168 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
169 if pos1 == nil or pos2 == nil then
\r
170 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
174 local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+([^%s]+)$")
\r
175 if found == nil then
\r
176 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
179 if not worldedit.node_is_valid(pos1, searchnode) then
\r
180 minetest.chat_send_player(name, "Invalid search node name: " .. searchnode)
\r
183 if not worldedit.node_is_valid(pos1, replacenode) then
\r
184 minetest.chat_send_player(name, "Invalid replace node name: " .. replacenode)
\r
188 local count = worldedit.replace(pos1, pos2, searchnode, replacenode)
\r
189 minetest.chat_send_player(name, count .. " nodes replaced")
\r
193 minetest.register_chatcommand("/hollowsphere", {
\r
194 params = "<radius> <node>",
\r
195 description = "Add hollow sphere at WorldEdit position 1 with radius <radius>, composed of <node>",
\r
196 privs = {worldedit=true},
\r
197 func = function(name, param)
\r
198 local pos = worldedit.pos1[name]
\r
200 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
204 local found, _, radius, nodename = param:find("^(%d+)%s+([^%s]+)$")
\r
205 if found == nil then
\r
206 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
209 if not worldedit.node_is_valid(pos, nodename) then
\r
210 minetest.chat_send_player(name, "Invalid node name: " .. param)
\r
214 local count = worldedit.hollow_sphere(pos, tonumber(radius), nodename)
\r
215 minetest.chat_send_player(name, count .. " nodes added")
\r
219 minetest.register_chatcommand("/sphere", {
\r
220 params = "<radius> <node>",
\r
221 description = "Add sphere at WorldEdit position 1 with radius <radius>, composed of <node>",
\r
222 privs = {worldedit=true},
\r
223 func = function(name, param)
\r
224 local pos = worldedit.pos1[name]
\r
226 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
230 local found, _, radius, nodename = param:find("^(%d+)%s+([^%s]+)$")
\r
231 if found == nil then
\r
232 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
235 if not worldedit.node_is_valid(pos, nodename) then
\r
236 minetest.chat_send_player(name, "Invalid node name: " .. param)
\r
240 local count = worldedit.sphere(pos, tonumber(radius), nodename)
\r
241 minetest.chat_send_player(name, count .. " nodes added")
\r
245 minetest.register_chatcommand("/hollowcylinder", {
\r
246 params = "x/y/z/? <length> <radius> <node>",
\r
247 description = "Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length> and radius <radius>, composed of <node>",
\r
248 privs = {worldedit=true},
\r
249 func = function(name, param)
\r
250 local pos = worldedit.pos1[name]
\r
252 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
256 local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+([^%s]+)$")
\r
257 if found == nil then
\r
258 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
261 if axis == "?" then
\r
262 axis, sign = worldedit.player_axis(name)
\r
263 length = length * sign
\r
265 if not worldedit.node_is_valid(pos, nodename) then
\r
266 minetest.chat_send_player(name, "Invalid node name: " .. param)
\r
270 local count = worldedit.hollow_cylinder(pos, axis, tonumber(length), tonumber(radius), nodename)
\r
271 minetest.chat_send_player(name, count .. " nodes added")
\r
275 minetest.register_chatcommand("/cylinder", {
\r
276 params = "x/y/z/? <length> <radius> <node>",
\r
277 description = "Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length> and radius <radius>, composed of <node>",
\r
278 privs = {worldedit=true},
\r
279 func = function(name, param)
\r
280 local pos = worldedit.pos1[name]
\r
282 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
286 local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+([^%s]+)$")
\r
287 if found == nil then
\r
288 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
291 if axis == "?" then
\r
292 axis, sign = worldedit.player_axis(name)
\r
293 length = length * sign
\r
295 if not worldedit.node_is_valid(pos, nodename) then
\r
296 minetest.chat_send_player(name, "Invalid node name: " .. param)
\r
300 local count = worldedit.cylinder(pos, axis, tonumber(length), tonumber(radius), nodename)
\r
301 minetest.chat_send_player(name, count .. " nodes added")
\r
305 minetest.register_chatcommand("/pyramid", {
\r
306 params = "<height> <node>",
\r
307 description = "Add pyramid at WorldEdit position 1 with height <height>, composed of <node>",
\r
308 privs = {worldedit=true},
\r
309 func = function(name, param)
\r
310 local pos = worldedit.pos1[name]
\r
312 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
316 local found, _, size, nodename = param:find("(%d+)%s+([^%s]+)$")
\r
317 if found == nil then
\r
318 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
321 if not worldedit.node_is_valid(pos, nodename) then
\r
322 minetest.chat_send_player(name, "Invalid node name: " .. param)
\r
326 local count = worldedit.pyramid(pos, tonumber(size), nodename)
\r
327 minetest.chat_send_player(name, count .. " nodes added")
\r
331 minetest.register_chatcommand("/spiral", {
\r
332 params = "<width> <height> <space> <node>",
\r
333 description = "Add spiral at WorldEdit position 1 with width <width>, height <height>, space between walls <space>, composed of <node>",
\r
334 privs = {worldedit=true},
\r
335 func = function(name, param)
\r
336 local pos = worldedit.pos1[name]
\r
338 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
342 local found, _, width, height, space, nodename = param:find("(%d+)%s+(%d+)%s+(%d+)%s+([^%s]+)$")
\r
343 if found == nil then
\r
344 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
347 if not worldedit.node_is_valid(pos, nodename) then
\r
348 minetest.chat_send_player(name, "Invalid node name: " .. param)
\r
352 local count = worldedit.spiral(pos, tonumber(width), tonumber(height), tonumber(space), nodename)
\r
353 minetest.chat_send_player(name, count .. " nodes changed")
\r
357 minetest.register_chatcommand("/copy", {
\r
358 params = "x/y/z/? <amount>",
\r
359 description = "Copy the current WorldEdit region along the x/y/z/? axis by <amount> nodes",
\r
360 privs = {worldedit=true},
\r
361 func = function(name, param)
\r
362 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
363 if pos1 == nil or pos2 == nil then
\r
364 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
368 local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$")
\r
369 if found == nil then
\r
370 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
373 if axis == "?" then
\r
374 axis, sign = worldedit.player_axis(name)
\r
375 amount = amount * sign
\r
378 local count = worldedit.copy(pos1, pos2, axis, tonumber(amount))
\r
379 minetest.chat_send_player(name, count .. " nodes copied")
\r
383 minetest.register_chatcommand("/move", {
\r
384 params = "x/y/z/? <amount>",
\r
385 description = "Move the current WorldEdit region along the x/y/z/? axis by <amount> nodes",
\r
386 privs = {worldedit=true},
\r
387 func = function(name, param)
\r
388 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
389 if pos1 == nil or pos2 == nil then
\r
390 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
394 local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$")
\r
395 if found == nil then
\r
396 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
399 if axis == "?" then
\r
400 axis, sign = worldedit.player_axis(name)
\r
401 amount = amount * sign
\r
404 local count = worldedit.move(pos1, pos2, axis, tonumber(amount))
\r
406 pos1[axis] = pos1[axis] + amount
\r
407 pos2[axis] = pos2[axis] + amount
\r
408 worldedit.mark_pos1(name)
\r
409 worldedit.mark_pos2(name)
\r
411 minetest.chat_send_player(name, count .. " nodes moved")
\r
415 minetest.register_chatcommand("/stack", {
\r
416 params = "x/y/z/? <count>",
\r
417 description = "Stack the current WorldEdit region along the x/y/z/? axis <count> times",
\r
418 privs = {worldedit=true},
\r
419 func = function(name, param)
\r
420 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
421 if pos1 == nil or pos2 == nil then
\r
422 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
426 local found, _, axis, count = param:find("^([xyz%?])%s+([+-]?%d+)$")
\r
427 if found == nil then
\r
428 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
431 if axis == "?" then
\r
432 axis, sign = worldedit.player_axis(name)
\r
433 count = count * sign
\r
436 local count = worldedit.stack(pos1, pos2, axis, tonumber(count))
\r
437 minetest.chat_send_player(name, count .. " nodes stacked")
\r
441 minetest.register_chatcommand("/transpose", {
\r
442 params = "x/y/z/? x/y/z/?",
\r
443 description = "Transpose the current WorldEdit region along the x/y/z/? and x/y/z/? axes",
\r
444 privs = {worldedit=true},
\r
445 func = function(name, param)
\r
446 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
447 if pos1 == nil or pos2 == nil then
\r
448 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
452 local found, _, axis1, axis2 = param:find("^([xyz%?])%s+([xyz%?])$")
\r
453 if found == nil then
\r
454 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
457 if axis1 == "?" then
\r
458 axis1 = worldedit.player_axis(name)
\r
460 if axis2 == "?" then
\r
461 axis2 = worldedit.player_axis(name)
\r
463 if axis1 == axis2 then
\r
464 minetest.chat_send_player(name, "Invalid usage: axes are the same")
\r
468 local count = worldedit.transpose(pos1, pos2, axis1, axis2)
\r
469 minetest.chat_send_player(name, count .. " nodes transposed")
\r
473 minetest.register_chatcommand("/flip", {
\r
474 params = "x/y/z/?",
\r
475 description = "Flip the current WorldEdit region along the x/y/z/? axis",
\r
476 privs = {worldedit=true},
\r
477 func = function(name, param)
\r
478 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
479 if pos1 == nil or pos2 == nil then
\r
480 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
484 if param == "?" then
\r
485 param = worldedit.player_axis(name)
\r
487 if param ~= "x" and param ~= "y" and param ~= "z" then
\r
488 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
492 local count = worldedit.flip(pos1, pos2, param)
\r
493 minetest.chat_send_player(name, count .. " nodes flipped")
\r
497 minetest.register_chatcommand("/rotate", {
\r
498 params = "<axis> <angle>",
\r
499 description = "Rotate the current WorldEdit region around the axis <axis> by angle <angle> (90 degree increment)",
\r
500 privs = {worldedit=true},
\r
501 func = function(name, param)
\r
502 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
503 if pos1 == nil or pos2 == nil then
\r
504 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
508 local found, _, axis, angle = param:find("^([xyz%?])%s+([+-]?%d+)$")
\r
509 if found == nil then
\r
510 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
513 if axis == "?" then
\r
514 axis = worldedit.player_axis(name)
\r
516 if angle % 90 ~= 0 then
\r
517 minetest.chat_send_player(name, "Invalid usage: angle must be multiple of 90")
\r
521 local count = worldedit.rotate(pos1, pos2, axis, angle)
\r
522 minetest.chat_send_player(name, count .. " nodes rotated")
\r
526 minetest.register_chatcommand("/dig", {
\r
528 description = "Dig the current WorldEdit region",
\r
529 privs = {worldedit=true},
\r
530 func = function(name, param)
\r
531 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
532 if pos1 == nil or pos2 == nil then
\r
533 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
537 local count = worldedit.dig(pos1, pos2)
\r
538 minetest.chat_send_player(name, count .. " nodes dug")
\r
542 minetest.register_chatcommand("/save", {
\r
544 description = "Save the current WorldEdit region to \"(world folder)/schems/<file>.we\"",
\r
545 privs = {worldedit=true},
\r
546 func = function(name, param)
\r
547 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
548 if pos1 == nil or pos2 == nil then
\r
549 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
553 if param == "" then
\r
554 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
558 local result, count = worldedit.serialize(pos1, pos2)
\r
560 local path = minetest.get_worldpath() .. "/schems"
\r
561 local filename = path .. "/" .. param .. ".we"
\r
562 os.execute("mkdir \"" .. path .. "\"") --create directory if it does not already exist
\r
563 local file, err = io.open(filename, "wb")
\r
565 minetest.chat_send_player(name, "Could not save file to \"" .. filename .. "\"")
\r
572 minetest.chat_send_player(name, count .. " nodes saved")
\r
576 minetest.register_chatcommand("/load", {
\r
578 description = "Load nodes from \"(world folder)/schems/<file>.we\" with position 1 of the current WorldEdit region as the origin",
\r
579 privs = {worldedit=true},
\r
580 func = function(name, param)
\r
581 local pos1 = worldedit.pos1[name]
\r
582 if pos1 == nil then
\r
583 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
587 if param == "" then
\r
588 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
592 local filename = minetest.get_worldpath() .. "/schems/" .. param .. ".we"
\r
593 local file, err = io.open(filename, "rb")
\r
595 minetest.chat_send_player(name, "Could not open file \"" .. filename .. "\"")
\r
598 local value = file:read("*a")
\r
602 if value:find("{") then --old WorldEdit format
\r
603 count = worldedit.deserialize_old(pos1, value)
\r
604 else --new WorldEdit format
\r
605 count = worldedit.deserialize(pos1, value)
\r
608 minetest.chat_send_player(name, count .. " nodes loaded")
\r
612 minetest.register_chatcommand("/metasave", {
\r
614 description = "Save the current WorldEdit region to \"(world folder)/schems/<file>.wem\"",
\r
615 privs = {worldedit=true},
\r
616 func = function(name, param)
\r
617 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
\r
618 if pos1 == nil or pos2 == nil then
\r
619 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
622 if param == "" then
\r
623 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
626 local count, err = worldedit.metasave(pos1, pos2, param)
\r
628 minetest.chat_send_player(name, "error loading file: " .. err)
\r
630 minetest.chat_send_player(name, count .. " nodes saved")
\r
635 minetest.register_chatcommand("/metaload", {
\r
637 description = "Load nodes from \"(world folder)/schems/<file>.wem\" with position 1 of the current WorldEdit region as the origin",
\r
638 privs = {worldedit=true},
\r
639 func = function(name, param)
\r
640 local pos1 = worldedit.pos1[name]
\r
641 if pos1 == nil then
\r
642 minetest.chat_send_player(name, "No WorldEdit region selected")
\r
645 if param == "" then
\r
646 minetest.chat_send_player(name, "Invalid usage: " .. param)
\r
649 local count, err = worldedit.metaload(pos1, param)
\r
651 minetest.chat_send_player(name, "error loading file: " .. err)
\r
653 minetest.chat_send_player(name, count .. " nodes loaded")
\r