]> git.lizzy.rs Git - worldedit.git/blob - init.lua
Add //hollowcylinder and //cylinder commands, add worldedit.hollow_cylinder and world...
[worldedit.git] / init.lua
1 minetest.register_privilege("worldedit", "Can use WorldEdit commands")\r
2 \r
3 worldedit = {}\r
4 \r
5 worldedit.set_pos = {}\r
6 \r
7 worldedit.pos1 = {}\r
8 worldedit.pos2 = {}\r
9 \r
10 dofile(minetest.get_modpath("worldedit") .. "/functions.lua")\r
11 dofile(minetest.get_modpath("worldedit") .. "/mark.lua")\r
12 \r
13 --determines whether `nodename` is a valid node name, returning a boolean\r
14 worldedit.node_is_valid = function(temp_pos, nodename)\r
15         return minetest.registered_nodes[nodename] ~= nil\r
16         or minetest.registered_nodes["default:" .. nodename] ~= nil\r
17 end\r
18 \r
19 minetest.register_chatcommand("/reset", {\r
20         params = "",\r
21         description = "Reset the region so that it is empty",\r
22         privs = {worldedit=true},\r
23         func = function(name, param)\r
24                 worldedit.pos1[name] = nil\r
25                 worldedit.pos2[name] = nil\r
26                 worldedit.mark_pos1(name)\r
27                 worldedit.mark_pos2(name)\r
28                 minetest.chat_send_player(name, "WorldEdit region reset")\r
29         end,\r
30 })\r
31 \r
32 minetest.register_chatcommand("/mark", {\r
33         params = "",\r
34         description = "Show markers at the region positions",\r
35         privs = {worldedit=true},\r
36         func = function(name, param)\r
37                 worldedit.mark_pos1(name)\r
38                 worldedit.mark_pos2(name)\r
39                 minetest.chat_send_player(name, "WorldEdit region marked")\r
40         end,\r
41 })\r
42 \r
43 minetest.register_chatcommand("/pos1", {\r
44         params = "",\r
45         description = "Set WorldEdit region position 1 to the player's location",\r
46         privs = {worldedit=true},\r
47         func = function(name, param)\r
48                 local pos = minetest.env:get_player_by_name(name):getpos()\r
49                 pos.x, pos.y, pos.z = math.floor(pos.x), math.floor(pos.y), math.floor(pos.z)\r
50                 worldedit.pos1[name] = pos\r
51                 worldedit.mark_pos1(name)\r
52                 minetest.chat_send_player(name, "WorldEdit position 1 set to " .. minetest.pos_to_string(pos))\r
53         end,\r
54 })\r
55 \r
56 minetest.register_chatcommand("/pos2", {\r
57         params = "",\r
58         description = "Set WorldEdit region position 2 to the player's location",\r
59         privs = {worldedit=true},\r
60         func = function(name, param)\r
61                 local pos = minetest.env:get_player_by_name(name):getpos()\r
62                 pos.x, pos.y, pos.z = math.floor(pos.x), math.floor(pos.y), math.floor(pos.z)\r
63                 worldedit.pos2[name] = pos\r
64                 worldedit.mark_pos2(name)\r
65                 minetest.chat_send_player(name, "WorldEdit position 2 set to " .. minetest.pos_to_string(pos))\r
66         end,\r
67 })\r
68 \r
69 minetest.register_chatcommand("/p", {\r
70         params = "set/get",\r
71         description = "Set WorldEdit region by punching two nodes, or display the current WorldEdit region",\r
72         privs = {worldedit=true},\r
73         func = function(name, param)\r
74                 if param == "set" then --set both WorldEdit positions\r
75                         worldedit.set_pos[name] = 1\r
76                         minetest.chat_send_player(name, "Select positions by punching two nodes")\r
77                 elseif param == "get" then --display current WorldEdit positions\r
78                         if worldedit.pos1[name] ~= nil then\r
79                                 minetest.chat_send_player(name, "WorldEdit position 1: " .. minetest.pos_to_string(worldedit.pos1[name]))\r
80                         else\r
81                                 minetest.chat_send_player(name, "WorldEdit position 1 not set")\r
82                         end\r
83                         if worldedit.pos2[name] ~= nil then\r
84                                 minetest.chat_send_player(name, "WorldEdit position 2: " .. minetest.pos_to_string(worldedit.pos2[name]))\r
85                         else\r
86                                 minetest.chat_send_player(name, "WorldEdit position 2 not set")\r
87                         end\r
88                 else\r
89                         minetest.chat_send_player(name, "Unknown subcommand: " .. param)\r
90                 end\r
91         end,\r
92 })\r
93 \r
94 minetest.register_on_punchnode(function(pos, node, puncher)\r
95         local name = puncher:get_player_name()\r
96         if name ~= "" and worldedit.set_pos[name] ~= nil then --currently setting position\r
97                 if worldedit.set_pos[name] == 1 then --setting position 1\r
98                         worldedit.set_pos[name] = 2 --set position 2 on the next invocation\r
99                         worldedit.pos1[name] = pos\r
100                         worldedit.mark_pos1(name)\r
101                         minetest.chat_send_player(name, "WorldEdit region position 1 set to " .. minetest.pos_to_string(pos))\r
102                 else --setting position 2\r
103                         worldedit.set_pos[name] = nil --finished setting positions\r
104                         worldedit.pos2[name] = pos\r
105                         worldedit.mark_pos2(name)\r
106                         minetest.chat_send_player(name, "WorldEdit region position 2 set to " .. minetest.pos_to_string(pos))\r
107                 end\r
108         end\r
109 end)\r
110 \r
111 minetest.register_chatcommand("/volume", {\r
112         params = "",\r
113         description = "Display the volume of the current WorldEdit region",\r
114         privs = {worldedit=true},\r
115         func = function(name, param)\r
116                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
117                 if pos1 == nil or pos2 == nil then\r
118                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
119                         return\r
120                 end\r
121 \r
122                 local volume = worldedit.volume(pos1, pos2)\r
123                 minetest.chat_send_player(name, "Current WorldEdit region has a volume of " .. volume .. " nodes (" .. pos2.x - pos1.x .. "*" .. pos2.y - pos1.y .. "*" .. pos2.z - pos1.z .. ")")\r
124         end,\r
125 })\r
126 \r
127 minetest.register_chatcommand("/set", {\r
128         params = "<node>",\r
129         description = "Set the current WorldEdit region to <node>",\r
130         privs = {worldedit=true},\r
131         func = function(name, param)\r
132                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
133                 if pos1 == nil or pos2 == nil then\r
134                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
135                         return\r
136                 end\r
137 \r
138                 if param == "" or not worldedit.node_is_valid(pos1, param) then\r
139                         minetest.chat_send_player(name, "Invalid node name: " .. param)\r
140                         return\r
141                 end\r
142 \r
143                 local count = worldedit.set(pos1, pos2, param)\r
144                 minetest.chat_send_player(name, count .. " nodes set")\r
145         end,\r
146 })\r
147 \r
148 minetest.register_chatcommand("/replace", {\r
149         params = "<search node> <replace node>",\r
150         description = "Replace all instances of <search node> with <place node> in the current WorldEdit region",\r
151         privs = {worldedit=true},\r
152         func = function(name, param)\r
153                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
154                 if pos1 == nil or pos2 == nil then\r
155                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
156                         return\r
157                 end\r
158 \r
159                 local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+([^%s]+)$")\r
160                 if found == nil then\r
161                         minetest.chat_send_player(name, "Invalid usage: " .. param)\r
162                         return\r
163                 end\r
164                 if not worldedit.node_is_valid(pos1, searchnode) then\r
165                         minetest.chat_send_player(name, "Invalid search node name: " .. searchnode)\r
166                         return\r
167                 end\r
168                 if not worldedit.node_is_valid(pos1, replacenode) then\r
169                         minetest.chat_send_player(name, "Invalid replace node name: " .. replacenode)\r
170                         return\r
171                 end\r
172 \r
173                 local count = worldedit.replace(pos1, pos2, searchnode, replacenode)\r
174                 minetest.chat_send_player(name, count .. " nodes replaced")\r
175         end,\r
176 })\r
177 \r
178 minetest.register_chatcommand("/hollowcylinder", {\r
179         params = "x/y/z <length> <radius> <node>",\r
180         description = "Add hollow cylinder at WorldEdit position 1 along the x/y/z axis with length <length> and radius <radius>, composed of <node>",\r
181         privs = {worldedit=true},\r
182         func = function(name, param)\r
183                 local pos = worldedit.pos1[name]\r
184                 if pos == nil then\r
185                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
186                         return\r
187                 end\r
188 \r
189                 local found, _, axis, length, radius, nodename = param:find("^([xyz])%s+([+-]?%d+)%s+(%d+)%s+([^%s]+)$")\r
190                 if found == nil then\r
191                         minetest.chat_send_player(name, "Invalid usage: " .. param)\r
192                         return\r
193                 end\r
194                 if not worldedit.node_is_valid(pos, nodename) then\r
195                         minetest.chat_send_player(name, "Invalid node name: " .. param)\r
196                         return\r
197                 end\r
198 \r
199                 local count = worldedit.hollow_cylinder(pos, axis, tonumber(length), tonumber(radius), nodename)\r
200                 minetest.chat_send_player(name, count .. " nodes added")\r
201         end,\r
202 })\r
203 \r
204 minetest.register_chatcommand("/cylinder", {\r
205         params = "x/y/z <length> <radius> <node>",\r
206         description = "Add cylinder at WorldEdit position 1 along the x/y/z axis with length <length> and radius <radius>, composed of <node>",\r
207         privs = {worldedit=true},\r
208         func = function(name, param)\r
209                 local pos = worldedit.pos1[name]\r
210                 if pos == nil then\r
211                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
212                         return\r
213                 end\r
214 \r
215                 local found, _, axis, length, radius, nodename = param:find("^([xyz])%s+([+-]?%d+)%s+(%d+)%s+([^%s]+)$")\r
216                 if found == nil then\r
217                         minetest.chat_send_player(name, "Invalid usage: " .. param)\r
218                         return\r
219                 end\r
220                 if not worldedit.node_is_valid(pos, nodename) then\r
221                         minetest.chat_send_player(name, "Invalid node name: " .. param)\r
222                         return\r
223                 end\r
224 \r
225                 local count = worldedit.cylinder(pos, axis, tonumber(length), tonumber(radius), nodename)\r
226                 minetest.chat_send_player(name, count .. " nodes added")\r
227         end,\r
228 })\r
229 \r
230 minetest.register_chatcommand("/copy", {\r
231         params = "x/y/z <amount>",\r
232         description = "Copy the current WorldEdit region along the x/y/z axis by <amount> nodes",\r
233         privs = {worldedit=true},\r
234         func = function(name, param)\r
235                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
236                 if pos1 == nil or pos2 == nil then\r
237                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
238                         return\r
239                 end\r
240 \r
241                 local found, _, axis, amount = param:find("^([xyz])%s+([+-]?%d+)$")\r
242                 if found == nil then\r
243                         minetest.chat_send_player(name, "Invalid usage: " .. param)\r
244                         return\r
245                 end\r
246 \r
247                 local count = worldedit.copy(pos1, pos2, axis, tonumber(amount))\r
248                 minetest.chat_send_player(name, count .. " nodes copied")\r
249         end,\r
250 })\r
251 \r
252 minetest.register_chatcommand("/move", {\r
253         params = "x/y/z <amount>",\r
254         description = "Move the current WorldEdit region along the x/y/z axis by <amount> nodes",\r
255         privs = {worldedit=true},\r
256         func = function(name, param)\r
257                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
258                 if pos1 == nil or pos2 == nil then\r
259                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
260                         return\r
261                 end\r
262 \r
263                 local found, _, axis, amount = param:find("^([xyz])%s+([+-]?%d+)$")\r
264                 if found == nil then\r
265                         minetest.chat_send_player(name, "Invalid usage: " .. param)\r
266                         return\r
267                 end\r
268 \r
269                 local count = worldedit.move(pos1, pos2, axis, tonumber(amount))\r
270                 minetest.chat_send_player(name, count .. " nodes moved")\r
271         end,\r
272 })\r
273 \r
274 minetest.register_chatcommand("/stack", {\r
275         params = "x/y/z <count>",\r
276         description = "Stack the current WorldEdit region along the x/y/z axis <count> times",\r
277         privs = {worldedit=true},\r
278         func = function(name, param)\r
279                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
280                 if pos1 == nil or pos2 == nil then\r
281                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
282                         return\r
283                 end\r
284 \r
285                 local found, _, axis, count = param:find("^([xyz])%s+([+-]?%d+)$")\r
286                 if found == nil then\r
287                         minetest.chat_send_player(name, "Invalid usage: " .. param)\r
288                         return\r
289                 end\r
290 \r
291                 local count = worldedit.stack(pos1, pos2, axis, tonumber(count))\r
292                 minetest.chat_send_player(name, count .. " nodes stacked")\r
293         end,\r
294 })\r
295 \r
296 minetest.register_chatcommand("/transpose", {\r
297         params = "x/y/z x/y/z",\r
298         description = "Transpose the current WorldEdit region along the x/y/z and x/y/z axes",\r
299         privs = {worldedit=true},\r
300         func = function(name, param)\r
301                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
302                 if pos1 == nil or pos2 == nil then\r
303                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
304                         return\r
305                 end\r
306 \r
307                 local found, _, axis1, axis2 = param:find("^([xyz])%s+([xyz])$")\r
308                 if found == nil then\r
309                         minetest.chat_send_player(name, "Invalid usage: " .. param)\r
310                         return\r
311                 end\r
312                 if axis1 == axis2 then\r
313                         minetest.chat_send_player(name, "Invalid usage: axes are the same")\r
314                         return\r
315                 end\r
316 \r
317                 local count = worldedit.transpose(pos1, pos2, axis1, axis2)\r
318                 minetest.chat_send_player(name, count .. " nodes transposed")\r
319         end,\r
320 })\r
321 \r
322 minetest.register_chatcommand("/flip", {\r
323         params = "x/y/z",\r
324         description = "Flip the current WorldEdit region along the x/y/z axis",\r
325         privs = {worldedit=true},\r
326         func = function(name, param)\r
327                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
328                 if pos1 == nil or pos2 == nil then\r
329                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
330                         return\r
331                 end\r
332 \r
333                 if param ~= "x" and param ~= "y" and param ~= "z" then\r
334                         minetest.chat_send_player(name, "Invalid usage: " .. param)\r
335                         return\r
336                 end\r
337 \r
338                 local count = worldedit.flip(pos1, pos2, param)\r
339                 minetest.chat_send_player(name, count .. " nodes flipped")\r
340         end,\r
341 })\r
342 \r
343 minetest.register_chatcommand("/rotate", {\r
344         params = "<angle>",\r
345         description = "Rotate the current WorldEdit region around the y axis by angle <angle> (90 degree increment)",\r
346         privs = {worldedit=true},\r
347         func = function(name, param)\r
348                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
349                 if pos1 == nil or pos2 == nil then\r
350                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
351                         return\r
352                 end\r
353 \r
354                 angle = tonumber(param)\r
355                 if angle == nil then\r
356                         minetest.chat_send_player(name, "Invalid usage: " .. param)\r
357                         return\r
358                 end\r
359                 if angle % 90 ~= 0 then\r
360                         minetest.chat_send_player(name, "Invalid usage: angle must be multiple of 90")\r
361                         return\r
362                 end\r
363 \r
364                 local count = worldedit.rotate(pos1, pos2, angle)\r
365                 minetest.chat_send_player(name, count .. " nodes rotated")\r
366         end,\r
367 })\r
368 \r
369 minetest.register_chatcommand("/dig", {\r
370         params = "",\r
371         description = "Dig the current WorldEdit region",\r
372         privs = {worldedit=true},\r
373         func = function(name, param)\r
374                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
375                 if pos1 == nil or pos2 == nil then\r
376                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
377                         return\r
378                 end\r
379 \r
380                 local count = worldedit.dig(pos1, pos2)\r
381                 minetest.chat_send_player(name, count .. " nodes dug")\r
382         end,\r
383 })\r
384 \r
385 minetest.register_chatcommand("/save", {\r
386         params = "<file>",\r
387         description = "Save the current WorldEdit region to \"(world folder)/schems/<file>.we\"",\r
388         privs = {worldedit=true},\r
389         func = function(name, param)\r
390                 local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
391                 if pos1 == nil or pos2 == nil then\r
392                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
393                         return\r
394                 end\r
395 \r
396                 if param == "" then\r
397                         minetest.chat_send_player(name, "Invalid usage: " .. param)\r
398                         return\r
399                 end\r
400 \r
401                 local result, count = worldedit.serialize(pos1, pos2)\r
402 \r
403                 local path = minetest.get_worldpath() .. "/schems"\r
404                 local filename = path .. "/" .. param .. ".we"\r
405                 os.execute("mkdir \"" .. path .. "\"") --create directory if it does not already exist\r
406                 local file, err = io.open(filename, "wb")\r
407                 if err ~= nil then\r
408                         minetest.chat_send_player(name, "Could not save file to \"" .. filename .. "\"")\r
409                         return\r
410                 end\r
411                 file:write(result)\r
412                 file:flush()\r
413                 file:close()\r
414 \r
415                 minetest.chat_send_player(name, count .. " nodes saved")\r
416         end,\r
417 })\r
418 \r
419 minetest.register_chatcommand("/load", {\r
420         params = "<file>",\r
421         description = "Load nodes from \"(world folder)/schems/<file>.we\" with position 1 of the current WorldEdit region as the origin",\r
422         privs = {worldedit=true},\r
423         func = function(name, param)\r
424                 local pos1 = worldedit.pos1[name]\r
425                 if pos1 == nil then\r
426                         minetest.chat_send_player(name, "No WorldEdit region selected")\r
427                         return\r
428                 end\r
429 \r
430                 if param == "" then\r
431                         minetest.chat_send_player(name, "Invalid usage: " .. param)\r
432                         return\r
433                 end\r
434 \r
435                 local filename = minetest.get_worldpath() .. "/schems/" .. param .. ".we"\r
436                 local file, err = io.open(filename, "rb")\r
437                 if err ~= nil then\r
438                         minetest.chat_send_player(name, "Could not open file \"" .. filename .. "\"")\r
439                         return\r
440                 end\r
441                 local value = file:read("*a")\r
442                 file:close()\r
443 \r
444                 local count\r
445                 if value:find("{") then --old WorldEdit format\r
446                         count = worldedit.deserialize_old(pos1, value)\r
447                 else --new WorldEdit format\r
448                         count = worldedit.deserialize(pos1, value)\r
449                 end\r
450 \r
451                 minetest.chat_send_player(name, count .. " nodes loaded")\r
452         end,\r
453 })