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