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