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