]> git.lizzy.rs Git - worldedit.git/blob - worldedit_brush/init.lua
b73a40231db73a3b2e2c16ade15328cd99af4f62
[worldedit.git] / worldedit_brush / init.lua
1 if minetest.raycast == nil then
2         error(
3                 "================================\n"..
4                 "This mod requires a suitable version of 0.4.16-dev/0.5.0-dev\n"..
5                 "that includes support for minetest.raycast() [since 7th July 2017]\n"..
6                 "================================\n"
7         )
8 end
9
10 local BRUSH_MAX_DIST = 150
11 local BRUSH_ALLOWED_COMMANDS = {
12         -- basically everything that only needs pos1
13         "cube",
14         "cylinder",
15         "dome",
16         "hollowcube",
17         "hollowcylinder",
18         "hollowdome",
19         "hollowpyramid",
20         "hollowsphere",
21         "load",
22         "pyramid",
23         "sphere",
24         "spiral",
25
26         "cyl",
27         "do",
28         "hcube",
29         "hcyl",
30         "hdo",
31         "hpyr",
32         "hspr",
33         "l",
34         "pyr",
35         "spr",
36         "spl",
37 }
38 local brush_on_use = function(itemstack, placer)
39         local meta = itemstack:get_meta()
40         local name = placer:get_player_name()
41
42         local cmd = meta:get_string("command")
43         if cmd == "" then
44                 worldedit.player_notify(name,
45                         "This brush is not bound, use //brush to bind a command to it.")
46                 return false
47         end
48         local cmddef = minetest.registered_chatcommands["/" .. cmd]
49         if cmddef == nil then return false end -- shouldn't happen as //brush checks this
50         local has_privs, missing_privs = minetest.check_player_privs(name, cmddef.privs)
51         if not has_privs then
52                 worldedit.player_notify(name,
53                         "Missing privileges: " .. table.concat(missing_privs, ", "))
54                 return false
55         end
56
57         local raybegin = vector.add(placer:get_pos(), {x=0, y=2, z=0}) -- player head
58         local rayend = vector.add(raybegin, vector.multiply(placer:get_look_dir(), BRUSH_MAX_DIST))
59         local ray = minetest.raycast(raybegin, rayend, false, true)
60         local pointed_thing = ray:next()
61         if pointed_thing == nil then
62                 worldedit.player_notify(name, "Too far away.")
63                 return false
64         end
65
66         assert(pointed_thing.type == "node")
67         worldedit.pos1[name] = pointed_thing.under
68         worldedit.pos2[name] = nil
69         worldedit.mark_region(name)
70         -- is this a horrible hack? oh yes.
71         worldedit._override_safe_regions = true
72         local player_notify_old = worldedit.player_notify
73         worldedit.player_notify = function(name, msg)
74                 if string.match(msg, "^%d") then return end -- discard "1234 nodes added."
75                 return player_notify_old(name, msg)
76         end
77
78         minetest.log("action", string.format("%s uses WorldEdit brush (//%s) at %s",
79                 name, cmd, minetest.pos_to_string(pointed_thing.under)))
80         cmddef.func(name, meta:get_string("params"))
81
82         worldedit._override_safe_regions = false
83         worldedit.player_notify = player_notify_old
84         return true
85 end
86
87 minetest.register_tool(":worldedit:brush", {
88         description = "WorldEdit Brush",
89         inventory_image = "worldedit_brush.png",
90         stack_max = 1, -- no need to stack these (metadata prevents this anyway)
91         range = 0,
92         on_use = function(itemstack, placer, pointed_thing)
93                 brush_on_use(itemstack, placer)
94                 return itemstack -- nothing consumed, nothing changed
95         end,
96 })
97
98 minetest.register_chatcommand("/brush", {
99         privs = {worldedit=true},
100         params = "none/<cmd> [parameters]",
101         description = "Assign command to WorldEdit brush item",
102         func = function(name, param)
103                 local found, _, cmd, params = param:find("^([^%s]+)%s+(.+)$")
104                 if not found then
105                         params = ""
106                         found, _, cmd = param:find("^(.+)$")
107                 end
108                 if not found then
109                         worldedit.player_notify(name, "Invalid usage.")
110                         return
111                 end
112
113                 local itemstack = minetest.get_player_by_name(name):get_wielded_item()
114                 if itemstack == nil or itemstack:get_name() ~= "worldedit:brush" then
115                         worldedit.player_notify(name, "Not holding brush item.")
116                         return
117                 end
118
119                 cmd = cmd:lower()
120                 local meta = itemstack:get_meta()
121                 if cmd == "none" then
122                         meta:from_table(nil)
123                         worldedit.player_notify(name, "Brush assignment cleared.")
124                 else
125                         local cmddef
126                         if table.indexof(BRUSH_ALLOWED_COMMANDS, cmd) ~= -1 then
127                                 cmddef = minetest.registered_chatcommands["/" .. cmd]
128                         else
129                                 cmddef = nil
130                         end
131                         if cmddef == nil then
132                                 worldedit.player_notify(name, "Invalid command for brush use: //" .. cmd)
133                                 return
134                         end
135                         meta:set_string("command", cmd)
136                         meta:set_string("params", params)
137                         local fullcmd = "//" .. cmd .. " " .. params
138                         meta:set_string("description",
139                                 minetest.registered_tools["worldedit:brush"].description .. ": " .. fullcmd)
140                         worldedit.player_notify(name, "Brush assigned to command: " .. fullcmd)
141                 end
142                 minetest.get_player_by_name(name):set_wielded_item(itemstack)
143         end,
144 })