]> git.lizzy.rs Git - worldedit.git/blob - worldedit_commands/init.lua
69e9804a36ddb6c60144b2aaaddd5f2f22689d65
[worldedit.git] / worldedit_commands / init.lua
1 minetest.register_privilege("worldedit", "Can use WorldEdit commands")\r
2 \r
3 worldedit.set_pos = {}\r
4 \r
5 worldedit.pos1 = {}\r
6 worldedit.pos2 = {}\r
7 \r
8 dofile(minetest.get_modpath("worldedit_commands") .. "/mark.lua")\r
9 \r
10 worldedit.player_notify = function(name, message)\r
11         minetest.chat_send_player(name, "WorldEdit -!- " .. message, false)\r
12 end\r
13 \r
14 --determines whether `nodename` is a valid node name, returning a boolean\r
15 worldedit.normalize_nodename = function(nodename)\r
16         if minetest.registered_nodes[nodename] then --directly found node name\r
17                 return nodename\r
18         elseif minetest.registered_nodes["default:" .. nodename] then --found node name in default\r
19                 return "default:" .. nodename\r
20         end\r
21         for key, value in pairs(minetest.registered_nodes) do\r
22                 if key:find(":" .. nodename, 1, true) then --found in mod\r
23                         return key\r
24                 end\r
25         end\r
26         for key, value in pairs(minetest.registered_nodes) do\r
27                 if value.description:lower() == nodename:lower() then --found in description\r
28                         return key\r
29                 end\r
30         end\r
31         return nil\r
32 end\r
33 \r
34 --determines the axis in which a player is facing, returning an axis ("x", "y", or "z") and the sign (1 or -1)\r
35 worldedit.player_axis = function(name)\r
36         local dir = minetest.env:get_player_by_name(name):get_look_dir()\r
37         local x, y, z = math.abs(dir.x), math.abs(dir.y), math.abs(dir.z)\r
38         if x > y then\r
39                 if x > z then\r
40                         return "x", dir.x > 0 and 1 or -1\r
41                 end\r
42         elseif y > z then\r
43                 return "y", dir.y > 0 and 1 or -1\r
44         end\r
45         return "z", dir.z > 0 and 1 or -1\r
46 end\r
47 \r
48 minetest.register_chatcommand("/reset", {\r
49         params = "",\r
50         description = "Reset the region so that it is empty",\r
51         privs = {worldedit=true},\r
52         func = function(name, param)\r
53                 worldedit.pos1[name] = nil\r
54                 worldedit.pos2[name] = nil\r
55                 worldedit.mark_pos1(name)\r
56                 worldedit.mark_pos2(name)\r
57                 worldedit.set_pos[name] = nil\r
58                 worldedit.player_notify(name, "region reset")\r
59         end,\r
60 })\r
61 \r
62 minetest.register_chatcommand("/mark", {\r
63         params = "",\r
64         description = "Show markers at the region positions",\r
65         privs = {worldedit=true},\r
66         func = function(name, param)\r
67                 worldedit.mark_pos1(name)\r
68                 worldedit.mark_pos2(name)\r
69                 worldedit.player_notify(name, "region marked")\r
70         end,\r
71 })\r
72 \r
73 minetest.register_chatcommand("/unmark", {\r
74         params = "",\r
75         description = "Hide markers if currently shown",\r
76         privs = {worldedit=true},\r
77         func = function(name, param)\r
78                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
79                 worldedit.pos1[name] = nil\r
80                 worldedit.pos2[name] = nil\r
81                 worldedit.mark_pos1(name)\r
82                 worldedit.mark_pos2(name)\r
83                 worldedit.pos1[name] = pos1\r
84                 worldedit.pos2[name] = pos2\r
85                 worldedit.player_notify(name, "region unmarked")\r
86         end,\r
87 })\r
88 \r
89 minetest.register_chatcommand("/pos1", {\r
90         params = "",\r
91         description = "Set WorldEdit region position 1 to the player's location",\r
92         privs = {worldedit=true},\r
93         func = function(name, param)\r
94                 local pos = minetest.env:get_player_by_name(name):getpos()\r
95                 pos.x, pos.y, pos.z = math.floor(pos.x + 0.5), math.floor(pos.y + 0.5), math.floor(pos.z + 0.5)\r
96                 worldedit.pos1[name] = pos\r
97                 worldedit.mark_pos1(name)\r
98                 worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos))\r
99         end,\r
100 })\r
101 \r
102 minetest.register_chatcommand("/pos2", {\r
103         params = "",\r
104         description = "Set WorldEdit region position 2 to the player's location",\r
105         privs = {worldedit=true},\r
106         func = function(name, param)\r
107                 local pos = minetest.env:get_player_by_name(name):getpos()\r
108                 pos.x, pos.y, pos.z = math.floor(pos.x + 0.5), math.floor(pos.y + 0.5), math.floor(pos.z + 0.5)\r
109                 worldedit.pos2[name] = pos\r
110                 worldedit.mark_pos2(name)\r
111                 worldedit.player_notify(name, "position 2 set to " .. minetest.pos_to_string(pos))\r
112         end,\r
113 })\r
114 \r
115 minetest.register_chatcommand("/p", {\r
116         params = "set/set1/set2/get",\r
117         description = "Set WorldEdit region, WorldEdit position 1, or WorldEdit position 2 by punching nodes, or display the current WorldEdit region",\r
118         privs = {worldedit=true},\r
119         func = function(name, param)\r
120                 if param == "set" then --set both WorldEdit positions\r
121                         worldedit.set_pos[name] = "pos1"\r
122                         worldedit.player_notify(name, "select positions by punching two nodes")\r
123                 elseif param == "set1" then --set WorldEdit position 1\r
124                         worldedit.set_pos[name] = "pos1only"\r
125                         worldedit.player_notify(name, "select position 1 by punching a node")\r
126                 elseif param == "set2" then --set WorldEdit position 2\r
127                         worldedit.set_pos[name] = "pos2"\r
128                         worldedit.player_notify(name, "select position 2 by punching a node")\r
129                 elseif param == "get" then --display current WorldEdit positions\r
130                         if worldedit.pos1[name] ~= nil then\r
131                                 worldedit.player_notify(name, "position 1: " .. minetest.pos_to_string(worldedit.pos1[name]))\r
132                         else\r
133                                 worldedit.player_notify(name, "position 1 not set")\r
134                         end\r
135                         if worldedit.pos2[name] ~= nil then\r
136                                 worldedit.player_notify(name, "position 2: " .. minetest.pos_to_string(worldedit.pos2[name]))\r
137                         else\r
138                                 worldedit.player_notify(name, "position 2 not set")\r
139                         end\r
140                 else\r
141                         worldedit.player_notify(name, "unknown subcommand: " .. param)\r
142                 end\r
143         end,\r
144 })\r
145 \r
146 minetest.register_on_punchnode(function(pos, node, puncher)\r
147         local name = puncher:get_player_name()\r
148         if name ~= "" and worldedit.set_pos[name] ~= nil then --currently setting position\r
149                 if worldedit.set_pos[name] == "pos1" then --setting position 1\r
150                         worldedit.pos1[name] = pos\r
151                         worldedit.mark_pos1(name)\r
152                         worldedit.set_pos[name] = "pos2" --set position 2 on the next invocation\r
153                         worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos))\r
154                 elseif worldedit.set_pos[name] == "pos1only" then --setting position 1 only\r
155                         worldedit.pos1[name] = pos\r
156                         worldedit.mark_pos1(name)\r
157                         worldedit.set_pos[name] = nil --finished setting positions\r
158                         worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos))\r
159                 elseif worldedit.set_pos[name] == "pos2" then --setting position 2\r
160                         worldedit.pos2[name] = pos\r
161                         worldedit.mark_pos2(name)\r
162                         worldedit.set_pos[name] = nil --finished setting positions\r
163                         worldedit.player_notify(name, "position 2 set to " .. minetest.pos_to_string(pos))\r
164                 end\r
165         end\r
166 end)\r
167 \r
168 minetest.register_chatcommand("/volume", {\r
169         params = "",\r
170         description = "Display the volume of the current WorldEdit region",\r
171         privs = {worldedit=true},\r
172         func = function(name, param)\r
173                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
174                 if pos1 == nil or pos2 == nil then\r
175                         worldedit.player_notify(name, "no region selected")\r
176                         return\r
177                 end\r
178 \r
179                 local volume = worldedit.volume(pos1, pos2)\r
180                 worldedit.player_notify(name, "current region has a volume of " .. volume .. " nodes (" .. pos2.x - pos1.x .. "*" .. pos2.y - pos1.y .. "*" .. pos2.z - pos1.z .. ")")\r
181         end,\r
182 })\r
183 \r
184 minetest.register_chatcommand("/set", {\r
185         params = "<node>",\r
186         description = "Set the current WorldEdit region to <node>",\r
187         privs = {worldedit=true},\r
188         func = function(name, param)\r
189                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
190                 if pos1 == nil or pos2 == nil then\r
191                         worldedit.player_notify(name, "no region selected")\r
192                         return\r
193                 end\r
194 \r
195                 local node = worldedit.normalize_nodename(param)\r
196                 if param == "" or not node then\r
197                         worldedit.player_notify(name, "invalid node name: " .. param)\r
198                         return\r
199                 end\r
200 \r
201                 local tenv = minetest.env\r
202                 if worldedit.ENABLE_QUEUE then\r
203                         tenv = worldedit.queue_aliasenv\r
204                 end\r
205 \r
206                 local count = worldedit.set(pos1, pos2, node, tenv)\r
207                 worldedit.player_notify(name, count .. " nodes set")\r
208         end,\r
209 })\r
210 \r
211 minetest.register_chatcommand("/replace", {\r
212         params = "<search node> <replace node>",\r
213         description = "Replace all instances of <search node> with <replace node> in the current WorldEdit region",\r
214         privs = {worldedit=true},\r
215         func = function(name, param)\r
216                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
217                 if pos1 == nil or pos2 == nil then\r
218                         worldedit.player_notify(name, "no region selected")\r
219                         return\r
220                 end\r
221 \r
222                 local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$")\r
223                 if found == nil then\r
224                         worldedit.player_notify(name, "invalid usage: " .. param)\r
225                         return\r
226                 end\r
227                 local newsearchnode = worldedit.normalize_nodename(searchnode)\r
228                 if not newsearchnode then\r
229                         worldedit.player_notify(name, "invalid search node name: " .. searchnode)\r
230                         return\r
231                 end\r
232                 local newreplacenode = worldedit.normalize_nodename(replacenode)\r
233                 if not newreplacenode then\r
234                         worldedit.player_notify(name, "invalid replace node name: " .. replacenode)\r
235                         return\r
236                 end\r
237 \r
238                 local tenv = minetest.env\r
239                 if worldedit.ENABLE_QUEUE then\r
240                         tenv = worldedit.queue_aliasenv\r
241                 end\r
242                 local count = worldedit.replace(pos1, pos2, newsearchnode, newreplacenode, tenv)\r
243                 worldedit.player_notify(name, count .. " nodes replaced")\r
244         end,\r
245 })\r
246 \r
247 minetest.register_chatcommand("/replaceinverse", {\r
248         params = "<search node> <replace node>",\r
249         description = "Replace all nodes other than <search node> with <replace node> in the current WorldEdit region",\r
250         privs = {worldedit=true},\r
251         func = function(name, param)\r
252                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
253                 if pos1 == nil or pos2 == nil then\r
254                         worldedit.player_notify(name, "no region selected")\r
255                         return\r
256                 end\r
257 \r
258                 local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$")\r
259                 if found == nil then\r
260                         worldedit.player_notify(name, "invalid usage: " .. param)\r
261                         return\r
262                 end\r
263                 local newsearchnode = worldedit.normalize_nodename(searchnode)\r
264                 if not newsearchnode then\r
265                         worldedit.player_notify(name, "invalid search node name: " .. searchnode)\r
266                         return\r
267                 end\r
268                 local newreplacenode = worldedit.normalize_nodename(replacenode)\r
269                 if not newreplacenode then\r
270                         worldedit.player_notify(name, "invalid replace node name: " .. replacenode)\r
271                         return\r
272                 end\r
273 \r
274                 local tenv = minetest.env\r
275                 if worldedit.ENABLE_QUEUE then\r
276                         tenv = worldedit.queue_aliasenv\r
277                 end\r
278                 local count = worldedit.replaceinverse(pos1, pos2, searchnode, replacenode, tenv)\r
279                 worldedit.player_notify(name, count .. " nodes replaced")\r
280         end,\r
281 })\r
282 \r
283 minetest.register_chatcommand("/hollowsphere", {\r
284         params = "<radius> <node>",\r
285         description = "Add hollow sphere at WorldEdit position 1 with radius <radius>, composed of <node>",\r
286         privs = {worldedit=true},\r
287         func = function(name, param)\r
288                 local pos = worldedit.pos1[name]\r
289                 if pos == nil then\r
290                         worldedit.player_notify(name, "no region selected")\r
291                         return\r
292                 end\r
293 \r
294                 local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$")\r
295                 if found == nil then\r
296                         worldedit.player_notify(name, "invalid usage: " .. param)\r
297                         return\r
298                 end\r
299                 local node = worldedit.normalize_nodename(nodename)\r
300                 if not node then\r
301                         worldedit.player_notify(name, "invalid node name: " .. nodename)\r
302                         return\r
303                 end\r
304 \r
305                 local tenv = minetest.env\r
306                 if worldedit.ENABLE_QUEUE then\r
307                         tenv = worldedit.queue_aliasenv\r
308                 end\r
309                 local count = worldedit.hollow_sphere(pos, tonumber(radius), node, tenv)\r
310                 worldedit.player_notify(name, count .. " nodes added")\r
311         end,\r
312 })\r
313 \r
314 minetest.register_chatcommand("/sphere", {\r
315         params = "<radius> <node>",\r
316         description = "Add sphere at WorldEdit position 1 with radius <radius>, composed of <node>",\r
317         privs = {worldedit=true},\r
318         func = function(name, param)\r
319                 local pos = worldedit.pos1[name]\r
320                 if pos == nil then\r
321                         worldedit.player_notify(name, "no region selected")\r
322                         return\r
323                 end\r
324 \r
325                 local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$")\r
326                 if found == nil then\r
327                         worldedit.player_notify(name, "invalid usage: " .. param)\r
328                         return\r
329                 end\r
330                 local node = worldedit.normalize_nodename(nodename)\r
331                 if not node then\r
332                         worldedit.player_notify(name, "invalid node name: " .. nodename)\r
333                         return\r
334                 end\r
335 \r
336                 local tenv = minetest.env\r
337                 if worldedit.ENABLE_QUEUE then\r
338                         tenv = worldedit.queue_aliasenv\r
339                 end\r
340                 local count = worldedit.sphere(pos, tonumber(radius), node, tenv)\r
341                 worldedit.player_notify(name, count .. " nodes added")\r
342         end,\r
343 })\r
344 \r
345 minetest.register_chatcommand("/hollowdome", {\r
346         params = "<radius> <node>",\r
347         description = "Add hollow dome at WorldEdit position 1 with radius <radius>, composed of <node>",\r
348         privs = {worldedit=true},\r
349         func = function(name, param)\r
350                 local pos = worldedit.pos1[name]\r
351                 if pos == nil then\r
352                         worldedit.player_notify(name, "no region selected")\r
353                         return\r
354                 end\r
355 \r
356                 local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$")\r
357                 if found == nil then\r
358                         worldedit.player_notify(name, "invalid usage: " .. param)\r
359                         return\r
360                 end\r
361                 local node = worldedit.normalize_nodename(nodename)\r
362                 if not node then\r
363                         worldedit.player_notify(name, "invalid node name: " .. nodename)\r
364                         return\r
365                 end\r
366 \r
367                 local tenv = minetest.env\r
368                 if worldedit.ENABLE_QUEUE then\r
369                         tenv = worldedit.queue_aliasenv\r
370                 end\r
371                 local count = worldedit.hollow_dome(pos, tonumber(radius), node, tenv)\r
372                 worldedit.player_notify(name, count .. " nodes added")\r
373         end,\r
374 })\r
375 \r
376 minetest.register_chatcommand("/dome", {\r
377         params = "<radius> <node>",\r
378         description = "Add dome at WorldEdit position 1 with radius <radius>, composed of <node>",\r
379         privs = {worldedit=true},\r
380         func = function(name, param)\r
381                 local pos = worldedit.pos1[name]\r
382                 if pos == nil then\r
383                         worldedit.player_notify(name, "no region selected")\r
384                         return\r
385                 end\r
386 \r
387                 local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$")\r
388                 if found == nil then\r
389                         worldedit.player_notify(name, "invalid usage: " .. param)\r
390                         return\r
391                 end\r
392                 local node = worldedit.normalize_nodename(nodename)\r
393                 if not node then\r
394                         worldedit.player_notify(name, "invalid node name: " .. nodename)\r
395                         return\r
396                 end\r
397 \r
398                 local tenv = minetest.env\r
399                 if worldedit.ENABLE_QUEUE then\r
400                         tenv = worldedit.queue_aliasenv\r
401                 end\r
402                 local count = worldedit.dome(pos, tonumber(radius), node, tenv)\r
403                 worldedit.player_notify(name, count .. " nodes added")\r
404         end,\r
405 })\r
406 \r
407 minetest.register_chatcommand("/hollowcylinder", {\r
408         params = "x/y/z/? <length> <radius> <node>",\r
409         description = "Add hollow cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length> and radius <radius>, composed of <node>",\r
410         privs = {worldedit=true},\r
411         func = function(name, param)\r
412                 local pos = worldedit.pos1[name]\r
413                 if pos == nil then\r
414                         worldedit.player_notify(name, "no region selected")\r
415                         return\r
416                 end\r
417 \r
418                 local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$")\r
419                 if found == nil then\r
420                         worldedit.player_notify(name, "invalid usage: " .. param)\r
421                         return\r
422                 end\r
423                 if axis == "?" then\r
424                         axis, sign = worldedit.player_axis(name)\r
425                         length = length * sign\r
426                 end\r
427                 local node = worldedit.normalize_nodename(nodename)\r
428                 if not node then\r
429                         worldedit.player_notify(name, "invalid node name: " .. nodename)\r
430                         return\r
431                 end\r
432 \r
433                 local tenv = minetest.env\r
434                 if worldedit.ENABLE_QUEUE then\r
435                         tenv = worldedit.queue_aliasenv\r
436                 end\r
437                 local count = worldedit.hollow_cylinder(pos, axis, tonumber(length), tonumber(radius), node, tenv)\r
438                 worldedit.player_notify(name, count .. " nodes added")\r
439         end,\r
440 })\r
441 \r
442 minetest.register_chatcommand("/cylinder", {\r
443         params = "x/y/z/? <length> <radius> <node>",\r
444         description = "Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length <length> and radius <radius>, composed of <node>",\r
445         privs = {worldedit=true},\r
446         func = function(name, param)\r
447                 local pos = worldedit.pos1[name]\r
448                 if pos == nil then\r
449                         worldedit.player_notify(name, "no region selected")\r
450                         return\r
451                 end\r
452 \r
453                 local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$")\r
454                 if found == nil then\r
455                         worldedit.player_notify(name, "invalid usage: " .. param)\r
456                         return\r
457                 end\r
458                 if axis == "?" then\r
459                         axis, sign = worldedit.player_axis(name)\r
460                         length = length * sign\r
461                 end\r
462                 local node = worldedit.normalize_nodename(nodename)\r
463                 if not node then\r
464                         worldedit.player_notify(name, "invalid node name: " .. nodename)\r
465                         return\r
466                 end\r
467 \r
468                 local tenv = minetest.env\r
469                 if worldedit.ENABLE_QUEUE then\r
470                         tenv = worldedit.queue_aliasenv\r
471                 end\r
472                 local count = worldedit.cylinder(pos, axis, tonumber(length), tonumber(radius), node, tenv)\r
473                 worldedit.player_notify(name, count .. " nodes added")\r
474         end,\r
475 })\r
476 \r
477 minetest.register_chatcommand("/pyramid", {\r
478         params = "<height> <node>",\r
479         description = "Add pyramid at WorldEdit position 1 with height <height>, composed of <node>",\r
480         privs = {worldedit=true},\r
481         func = function(name, param)\r
482                 local pos = worldedit.pos1[name]\r
483                 if pos == nil then\r
484                         worldedit.player_notify(name, "no region selected")\r
485                         return\r
486                 end\r
487 \r
488                 local found, _, size, nodename = param:find("(%d+)%s+(.+)$")\r
489                 if found == nil then\r
490                         worldedit.player_notify(name, "invalid usage: " .. param)\r
491                         return\r
492                 end\r
493                 local node = worldedit.normalize_nodename(nodename)\r
494                 if not node then\r
495                         worldedit.player_notify(name, "invalid node name: " .. nodename)\r
496                         return\r
497                 end\r
498 \r
499                 local tenv = minetest.env\r
500                 if worldedit.ENABLE_QUEUE then\r
501                         tenv = worldedit.queue_aliasenv\r
502                 end\r
503                 local count = worldedit.pyramid(pos, tonumber(size), node, tenv)\r
504                 worldedit.player_notify(name, count .. " nodes added")\r
505         end,\r
506 })\r
507 \r
508 minetest.register_chatcommand("/spiral", {\r
509         params = "<width> <height> <space> <node>",\r
510         description = "Add spiral at WorldEdit position 1 with width <width>, height <height>, space between walls <space>, composed of <node>",\r
511         privs = {worldedit=true},\r
512         func = function(name, param)\r
513                 local pos = worldedit.pos1[name]\r
514                 if pos == nil then\r
515                         worldedit.player_notify(name, "no region selected")\r
516                         return\r
517                 end\r
518 \r
519                 local found, _, width, height, space, nodename = param:find("(%d+)%s+(%d+)%s+(%d+)%s+(.+)$")\r
520                 if found == nil then\r
521                         worldedit.player_notify(name, "invalid usage: " .. param)\r
522                         return\r
523                 end\r
524                 local node = worldedit.normalize_nodename(nodename)\r
525                 if not node then\r
526                         worldedit.player_notify(name, "invalid node name: " .. nodename)\r
527                         return\r
528                 end\r
529 \r
530                 local tenv = minetest.env\r
531                 if worldedit.ENABLE_QUEUE then\r
532                         tenv = worldedit.queue_aliasenv\r
533                 end\r
534                 local count = worldedit.spiral(pos, tonumber(width), tonumber(height), tonumber(space), node, tenv)\r
535                 worldedit.player_notify(name, count .. " nodes added")\r
536         end,\r
537 })\r
538 \r
539 minetest.register_chatcommand("/copy", {\r
540         params = "x/y/z/? <amount>",\r
541         description = "Copy the current WorldEdit region along the x/y/z/? axis by <amount> nodes",\r
542         privs = {worldedit=true},\r
543         func = function(name, param)\r
544                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
545                 if pos1 == nil or pos2 == nil then\r
546                         worldedit.player_notify(name, "no region selected")\r
547                         return\r
548                 end\r
549 \r
550                 local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$")\r
551                 if found == nil then\r
552                         worldedit.player_notify(name, "invalid usage: " .. param)\r
553                         return\r
554                 end\r
555                 if axis == "?" then\r
556                         axis, sign = worldedit.player_axis(name)\r
557                         amount = amount * sign\r
558                 end\r
559 \r
560                 local tenv = minetest.env\r
561                 if worldedit.ENABLE_QUEUE then\r
562                         tenv = worldedit.queue_aliasenv\r
563                 end\r
564                 local count = worldedit.copy(pos1, pos2, axis, tonumber(amount), tenv)\r
565                 worldedit.player_notify(name, count .. " nodes copied")\r
566         end,\r
567 })\r
568 \r
569 minetest.register_chatcommand("/move", {\r
570         params = "x/y/z/? <amount>",\r
571         description = "Move the current WorldEdit region along the x/y/z/? axis by <amount> nodes",\r
572         privs = {worldedit=true},\r
573         func = function(name, param)\r
574                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
575                 if pos1 == nil or pos2 == nil then\r
576                         worldedit.player_notify(name, "no region selected")\r
577                         return\r
578                 end\r
579 \r
580                 local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$")\r
581                 if found == nil then\r
582                         worldedit.player_notify(name, "invalid usage: " .. param)\r
583                         return\r
584                 end\r
585                 if axis == "?" then\r
586                         axis, sign = worldedit.player_axis(name)\r
587                         amount = amount * sign\r
588                 end\r
589 \r
590                 local tenv = minetest.env\r
591                 if worldedit.ENABLE_QUEUE then\r
592                         tenv = worldedit.queue_aliasenv\r
593                 end\r
594                 local count = worldedit.move(pos1, pos2, axis, tonumber(amount), tenv)\r
595 \r
596                 pos1[axis] = pos1[axis] + amount\r
597                 pos2[axis] = pos2[axis] + amount\r
598                 worldedit.mark_pos1(name)\r
599                 worldedit.mark_pos2(name)\r
600                 worldedit.player_notify(name, count .. " nodes moved")\r
601         end,\r
602 })\r
603 \r
604 minetest.register_chatcommand("/stack", {\r
605         params = "x/y/z/? <count>",\r
606         description = "Stack the current WorldEdit region along the x/y/z/? axis <count> times",\r
607         privs = {worldedit=true},\r
608         func = function(name, param)\r
609                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
610                 if pos1 == nil or pos2 == nil then\r
611                         worldedit.player_notify(name, "no region selected")\r
612                         return\r
613                 end\r
614 \r
615                 local found, _, axis, count = param:find("^([xyz%?])%s+([+-]?%d+)$")\r
616                 if found == nil then\r
617                         worldedit.player_notify(name, "invalid usage: " .. param)\r
618                         return\r
619                 end\r
620                 if axis == "?" then\r
621                         axis, sign = worldedit.player_axis(name)\r
622                         count = count * sign\r
623                 end\r
624 \r
625                 local tenv = minetest.env\r
626                 if worldedit.ENABLE_QUEUE then\r
627                         tenv = worldedit.queue_aliasenv\r
628                 end\r
629                 local count = worldedit.stack(pos1, pos2, axis, tonumber(count), tenv)\r
630                 worldedit.player_notify(name, count .. " nodes stacked")\r
631         end,\r
632 })\r
633 \r
634 minetest.register_chatcommand("/transpose", {\r
635         params = "x/y/z/? x/y/z/?",\r
636         description = "Transpose the current WorldEdit region along the x/y/z/? and x/y/z/? axes",\r
637         privs = {worldedit=true},\r
638         func = function(name, param)\r
639                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
640                 if pos1 == nil or pos2 == nil then\r
641                         worldedit.player_notify(name, "no region selected")\r
642                         return\r
643                 end\r
644 \r
645                 local found, _, axis1, axis2 = param:find("^([xyz%?])%s+([xyz%?])$")\r
646                 if found == nil then\r
647                         worldedit.player_notify(name, "invalid usage: " .. param)\r
648                         return\r
649                 end\r
650                 if axis1 == "?" then\r
651                         axis1 = worldedit.player_axis(name)\r
652                 end\r
653                 if axis2 == "?" then\r
654                         axis2 = worldedit.player_axis(name)\r
655                 end\r
656                 if axis1 == axis2 then\r
657                         worldedit.player_notify(name, "invalid usage: axes must be different")\r
658                         return\r
659                 end\r
660 \r
661                 local tenv = minetest.env\r
662                 if worldedit.ENABLE_QUEUE then\r
663                         tenv = worldedit.queue_aliasenv\r
664                 end\r
665                 local count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2, tenv)\r
666 \r
667                 --reset markers to transposed positions\r
668                 worldedit.pos1[name] = pos1\r
669                 worldedit.pos2[name] = pos2\r
670                 worldedit.mark_pos1(name)\r
671                 worldedit.mark_pos2(name)\r
672 \r
673                 worldedit.player_notify(name, count .. " nodes transposed")\r
674         end,\r
675 })\r
676 \r
677 minetest.register_chatcommand("/flip", {\r
678         params = "x/y/z/?",\r
679         description = "Flip the current WorldEdit region along the x/y/z/? axis",\r
680         privs = {worldedit=true},\r
681         func = function(name, param)\r
682                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
683                 if pos1 == nil or pos2 == nil then\r
684                         worldedit.player_notify(name, "no region selected")\r
685                         return\r
686                 end\r
687 \r
688                 if param == "?" then\r
689                         param = worldedit.player_axis(name)\r
690                 end\r
691                 if param ~= "x" and param ~= "y" and param ~= "z" then\r
692                         worldedit.player_notify(name, "invalid usage: " .. param)\r
693                         return\r
694                 end\r
695 \r
696                 local tenv = minetest.env\r
697                 if worldedit.ENABLE_QUEUE then\r
698                         tenv = worldedit.queue_aliasenv\r
699                 end\r
700                 local count = worldedit.flip(pos1, pos2, param, tenv)\r
701                 worldedit.player_notify(name, count .. " nodes flipped")\r
702         end,\r
703 })\r
704 \r
705 minetest.register_chatcommand("/rotate", {\r
706         params = "<axis> <angle>",\r
707         description = "Rotate the current WorldEdit region around the axis <axis> by angle <angle> (90 degree increment)",\r
708         privs = {worldedit=true},\r
709         func = function(name, param)\r
710                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
711                 if pos1 == nil or pos2 == nil then\r
712                         worldedit.player_notify(name, "no region selected")\r
713                         return\r
714                 end\r
715 \r
716                 local found, _, axis, angle = param:find("^([xyz%?])%s+([+-]?%d+)$")\r
717                 if found == nil then\r
718                         worldedit.player_notify(name, "invalid usage: " .. param)\r
719                         return\r
720                 end\r
721                 if axis == "?" then\r
722                         axis = worldedit.player_axis(name)\r
723                 end\r
724                 if angle % 90 ~= 0 then\r
725                         worldedit.player_notify(name, "invalid usage: angle must be multiple of 90")\r
726                         return\r
727                 end\r
728 \r
729                 local count, pos1, pos2 = worldedit.rotate(pos1, pos2, axis, angle)\r
730 \r
731                 --reset markers to rotated positions\r
732                 worldedit.pos1[name] = pos1\r
733                 worldedit.pos2[name] = pos2\r
734                 worldedit.mark_pos1(name)\r
735                 worldedit.mark_pos2(name)\r
736 \r
737                 worldedit.player_notify(name, count .. " nodes rotated")\r
738         end,\r
739 })\r
740 \r
741 minetest.register_chatcommand("/orient", {\r
742         params = "<angle>",\r
743         description = "Rotate oriented nodes in the current WorldEdit region around the Y axis by angle <angle> (90 degree increment)",\r
744         privs = {worldedit=true},\r
745         func = function(name, param)\r
746                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
747                 if pos1 == nil or pos2 == nil then\r
748                         worldedit.player_notify(name, "no region selected")\r
749                         return\r
750                 end\r
751 \r
752                 local found, _, angle = param:find("^([+-]?%d+)$")\r
753                 if found == nil then\r
754                         worldedit.player_notify(name, "invalid usage: " .. param)\r
755                         return\r
756                 end\r
757                 if angle % 90 ~= 0 then\r
758                         worldedit.player_notify(name, "invalid usage: angle must be multiple of 90")\r
759                         return\r
760                 end\r
761 \r
762                 local tenv = minetest.env\r
763                 if worldedit.ENABLE_QUEUE then\r
764                         tenv = worldedit.queue_aliasenv\r
765                 end\r
766                 local count = worldedit.orient(pos1, pos2, angle, tenv)\r
767 \r
768                 worldedit.player_notify(name, count .. " nodes oriented")\r
769         end,\r
770 })\r
771 \r
772 minetest.register_chatcommand("/fixlight", {\r
773         params = "",\r
774         description = "Fix the lighting in the current WorldEdit region",\r
775         privs = {worldedit=true},\r
776         func = function(name, param)\r
777                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
778                 if pos1 == nil or pos2 == nil then\r
779                         worldedit.player_notify(name, "no region selected")\r
780                         return\r
781                 end\r
782 \r
783                 local tenv = minetest.env\r
784                 if worldedit.ENABLE_QUEUE then\r
785                         tenv = worldedit.queue_aliasenv\r
786                 end\r
787                 local count = worldedit.fixlight(pos1, pos2, tenv)\r
788                 worldedit.player_notify(name, count .. " nodes updated")\r
789         end,\r
790 })\r
791 \r
792 minetest.register_chatcommand("/hide", {\r
793         params = "",\r
794         description = "Hide all nodes in the current WorldEdit region non-destructively",\r
795         privs = {worldedit=true},\r
796         func = function(name, param)\r
797                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
798                 if pos1 == nil or pos2 == nil then\r
799                         worldedit.player_notify(name, "no region selected")\r
800                         return\r
801                 end\r
802 \r
803                 local tenv = minetest.env\r
804                 if worldedit.ENABLE_QUEUE then\r
805                         tenv = worldedit.queue_aliasenv\r
806                 end\r
807                 local count = worldedit.hide(pos1, pos2, tenv)\r
808                 worldedit.player_notify(name, count .. " nodes hidden")\r
809         end,\r
810 })\r
811 \r
812 minetest.register_chatcommand("/suppress", {\r
813         params = "<node>",\r
814         description = "Suppress all <node> in the current WorldEdit region non-destructively",\r
815         privs = {worldedit=true},\r
816         func = function(name, param)\r
817                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
818                 if pos1 == nil or pos2 == nil then\r
819                         worldedit.player_notify(name, "no region selected")\r
820                         return\r
821                 end\r
822 \r
823                 local node = worldedit.node_is_valid(param)\r
824                 if param == "" or not node then\r
825                         worldedit.player_notify(name, "invalid node name: " .. param)\r
826                         return\r
827                 end\r
828 \r
829                 local tenv = minetest.env\r
830                 if worldedit.ENABLE_QUEUE then\r
831                         tenv = worldedit.queue_aliasenv\r
832                 end\r
833                 local count = worldedit.suppress(pos1, pos2, node, tenv)\r
834                 worldedit.player_notify(name, count .. " nodes suppressed")\r
835         end,\r
836 })\r
837 \r
838 minetest.register_chatcommand("/highlight", {\r
839         params = "<node>",\r
840         description = "Highlight <node> in the current WorldEdit region by hiding everything else non-destructively",\r
841         privs = {worldedit=true},\r
842         func = function(name, param)\r
843                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
844                 if pos1 == nil or pos2 == nil then\r
845                         worldedit.player_notify(name, "no region selected")\r
846                         return\r
847                 end\r
848 \r
849                 local node = worldedit.node_is_valid(param)\r
850                 if param == "" or not node then\r
851                         worldedit.player_notify(name, "invalid node name: " .. param)\r
852                         return\r
853                 end\r
854 \r
855                 local tenv = minetest.env\r
856                 if worldedit.ENABLE_QUEUE then\r
857                         tenv = worldedit.queue_aliasenv\r
858                 end\r
859                 local count = worldedit.highlight(pos1, pos2, node, tenv)\r
860                 worldedit.player_notify(name, count .. " nodes highlighted")\r
861         end,\r
862 })\r
863 \r
864 minetest.register_chatcommand("/restore", {\r
865         params = "",\r
866         description = "Restores nodes hidden with WorldEdit in the current WorldEdit region",\r
867         privs = {worldedit=true},\r
868         func = function(name, param)\r
869                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
870                 if pos1 == nil or pos2 == nil then\r
871                         worldedit.player_notify(name, "no region selected")\r
872                         return\r
873                 end\r
874 \r
875                 local tenv = minetest.env\r
876                 if worldedit.ENABLE_QUEUE then\r
877                         tenv = worldedit.queue_aliasenv\r
878                 end\r
879                 local count = worldedit.restore(pos1, pos2, tenv)\r
880                 worldedit.player_notify(name, count .. " nodes restored")\r
881         end,\r
882 })\r
883 \r
884 minetest.register_chatcommand("/save", {\r
885         params = "<file>",\r
886         description = "Save the current WorldEdit region to \"(world folder)/schems/<file>.we\"",\r
887         privs = {worldedit=true},\r
888         func = function(name, param)\r
889                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
890                 if pos1 == nil or pos2 == nil then\r
891                         worldedit.player_notify(name, "no region selected")\r
892                         return\r
893                 end\r
894 \r
895                 if param == "" then\r
896                         worldedit.player_notify(name, "invalid usage: " .. param)\r
897                         return\r
898                 end\r
899 \r
900                 local result, count = worldedit.serialize(pos1, pos2)\r
901 \r
902                 local path = minetest.get_worldpath() .. "/schems"\r
903                 local filename = path .. "/" .. param .. ".we"\r
904                 os.execute("mkdir \"" .. path .. "\"") --create directory if it does not already exist\r
905                 local file, err = io.open(filename, "wb")\r
906                 if err ~= nil then\r
907                         worldedit.player_notify(name, "could not save file to \"" .. filename .. "\"")\r
908                         return\r
909                 end\r
910                 file:write(result)\r
911                 file:flush()\r
912                 file:close()\r
913 \r
914                 worldedit.player_notify(name, count .. " nodes saved")\r
915         end,\r
916 })\r
917 \r
918 minetest.register_chatcommand("/allocate", {\r
919         params = "<file>",\r
920         description = "Set the region defined by nodes from \"(world folder)/schems/<file>.we\" as the current WorldEdit region",\r
921         privs = {worldedit=true},\r
922         func = function(name, param)\r
923                 local pos1 = worldedit.pos1[name]\r
924                 if pos1 == nil then\r
925                         worldedit.player_notify(name, "no region selected")\r
926                         return\r
927                 end\r
928 \r
929                 if param == "" then\r
930                         worldedit.player_notify(name, "invalid usage: " .. param)\r
931                         return\r
932                 end\r
933 \r
934                 local filename = minetest.get_worldpath() .. "/schems/" .. param .. ".we"\r
935                 local file, err = io.open(filename, "rb")\r
936                 if err ~= nil then\r
937                         worldedit.player_notify(name, "could not open file \"" .. filename .. "\"")\r
938                         return\r
939                 end\r
940                 local value = file:read("*a")\r
941                 file:close()\r
942 \r
943                 if worldedit.valueversion(value) == 0 then --unknown version\r
944                         worldedit.player_notify(name, "invalid file: file is invalid or created with newer version of WorldEdit")\r
945                         return\r
946                 end\r
947                 local nodepos1, nodepos2, count = worldedit.allocate(pos1, value)\r
948 \r
949                 worldedit.pos1[name] = nodepos1\r
950                 worldedit.mark_pos1(name)\r
951                 worldedit.pos2[name] = nodepos2\r
952                 worldedit.mark_pos2(name)\r
953 \r
954                 worldedit.player_notify(name, count .. " nodes allocated")\r
955         end,\r
956 })\r
957 \r
958 minetest.register_chatcommand("/load", {\r
959         params = "<file>",\r
960         description = "Load nodes from \"(world folder)/schems/<file>[.we[m]]\" with position 1 of the current WorldEdit region as the origin",\r
961         privs = {worldedit=true},\r
962         func = function(name, param)\r
963                 local pos1 = worldedit.pos1[name]\r
964                 if pos1 == nil then\r
965                         worldedit.player_notify(name, "no region selected")\r
966                         return\r
967                 end\r
968 \r
969                 if param == "" then\r
970                         worldedit.player_notify(name, "invalid usage: " .. param)\r
971                         return\r
972                 end\r
973 \r
974                 --find the file in the world path\r
975                 local testpaths = {\r
976                         minetest.get_worldpath() .. "/schems/" .. param,\r
977                         minetest.get_worldpath() .. "/schems/" .. param .. ".we",\r
978                         minetest.get_worldpath() .. "/schems/" .. param .. ".wem",\r
979                 }\r
980                 local file, err\r
981                 for index, path in ipairs(testpaths) do\r
982                         file, err = io.open(path, "rb")\r
983                         if not err then\r
984                                 break\r
985                         end\r
986                 end\r
987                 if err then\r
988                         worldedit.player_notify(name, "could not open file \"" .. param .. "\"")\r
989                         return\r
990                 end\r
991                 local value = file:read("*a")\r
992                 file:close()\r
993 \r
994                 if worldedit.valueversion(value) == 0 then --unknown version\r
995                         worldedit.player_notify(name, "invalid file: file is invalid or created with newer version of WorldEdit")\r
996                         return\r
997                 end\r
998 \r
999                 local tenv = minetest.env\r
1000                 if worldedit.ENABLE_QUEUE then\r
1001                         tenv = worldedit.queue_aliasenv\r
1002                 end\r
1003                 local count = worldedit.deserialize(pos1, value, tenv)\r
1004 \r
1005                 worldedit.player_notify(name, count .. " nodes loaded")\r
1006         end,\r
1007 })\r
1008 \r
1009 minetest.register_chatcommand("/lua", {\r
1010         params = "<code>",\r
1011         description = "Executes <code> as a Lua chunk in the global namespace",\r
1012         privs = {worldedit=true, server=true},\r
1013         func = function(name, param)\r
1014                 local err = worldedit.lua(param)\r
1015                 if err then\r
1016                         worldedit.player_notify(name, "code error: " .. err)\r
1017                 else\r
1018                         worldedit.player_notify(name, "code successfully executed", false)\r
1019                 end\r
1020         end,\r
1021 })\r
1022 \r
1023 minetest.register_chatcommand("/luatransform", {\r
1024         params = "<code>",\r
1025         description = "Executes <code> as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region",\r
1026         privs = {worldedit=true, server=true},\r
1027         func = function(name, param)\r
1028                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
1029                 if pos1 == nil or pos2 == nil then\r
1030                         worldedit.player_notify(name, "no region selected")\r
1031                         return\r
1032                 end\r
1033 \r
1034                 local err = worldedit.luatransform(pos1, pos2, param)\r
1035                 if err then\r
1036                         worldedit.player_notify(name, "code error: " .. err, false)\r
1037                 else\r
1038                         worldedit.player_notify(name, "code successfully executed", false)\r
1039                 end\r
1040         end,\r
1041 })\r