]> git.lizzy.rs Git - worldedit.git/blob - worldedit_brush/init.lua
369b6b5332ef731126016e86a3caae310fbd6057
[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_on_use = function(itemstack, placer)
9         local meta = itemstack:get_meta()
10         local name = placer:get_player_name()
11
12         local cmd = meta:get_string("command")
13         if cmd == "" then
14                 worldedit.player_notify(name,
15                         "This brush is not bound, use //brush to bind a command to it.")
16                 return false
17         end
18
19         local cmddef = worldedit.registered_commands[cmd]
20         if cmddef == nil then return false end -- shouldn't happen as //brush checks this
21
22         local has_privs, missing_privs = minetest.check_player_privs(name, cmddef.privs)
23         if not has_privs then
24                 worldedit.player_notify(name,
25                         "Missing privileges: " .. table.concat(missing_privs, ", "))
26                 return false
27         end
28
29         local raybegin = vector.add(placer:get_pos(),
30                 {x=0, y=placer:get_properties().eye_height, z=0})
31         local rayend = vector.add(raybegin, vector.multiply(placer:get_look_dir(), BRUSH_MAX_DIST))
32         local ray = minetest.raycast(raybegin, rayend, false, true)
33         local pointed_thing = ray:next()
34         if pointed_thing == nil then
35                 worldedit.player_notify(name, "Too far away.")
36                 return false
37         end
38
39         assert(pointed_thing.type == "node")
40         worldedit.pos1[name] = pointed_thing.under
41         worldedit.pos2[name] = nil
42         worldedit.marker_update(name)
43
44         -- this isn't really clean...
45         local player_notify_old = worldedit.player_notify
46         worldedit.player_notify = function(name, msg)
47                 if string.match(msg, "^%d") then return end -- discard "1234 nodes added."
48                 return player_notify_old(name, msg)
49         end
50
51         assert(cmddef.require_pos < 2)
52         local parsed = {cmddef.parse(meta:get_string("params"))}
53         if not table.remove(parsed, 1) then return false end -- shouldn't happen
54
55         minetest.log("action", string.format("%s uses WorldEdit brush (//%s) at %s",
56                 name, cmd, minetest.pos_to_string(pointed_thing.under)))
57         cmddef.func(name, unpack(parsed))
58
59         worldedit.player_notify = player_notify_old
60         return true
61 end
62
63 minetest.register_tool(":worldedit:brush", {
64         description = "WorldEdit Brush",
65         inventory_image = "worldedit_brush.png",
66         stack_max = 1, -- no need to stack these (metadata prevents this anyway)
67         range = 0,
68         on_use = function(itemstack, placer, pointed_thing)
69                 brush_on_use(itemstack, placer)
70                 return itemstack -- nothing consumed, nothing changed
71         end,
72 })
73
74 worldedit.register_command("brush", {
75         privs = {worldedit=true},
76         params = "none/<cmd> [parameters]",
77         description = "Assign command to WorldEdit brush item",
78         parse = function(param)
79                 local found, _, cmd, params = param:find("^([^%s]+)%s+(.+)$")
80                 if not found then
81                         params = ""
82                         found, _, cmd = param:find("^(.+)$")
83                 end
84                 if not found then
85                         return false
86                 end
87                 return true, cmd, params
88         end,
89         func = function(name, cmd, params)
90                 local itemstack = minetest.get_player_by_name(name):get_wielded_item()
91                 if itemstack == nil or itemstack:get_name() ~= "worldedit:brush" then
92                         worldedit.player_notify(name, "Not holding brush item.")
93                         return
94                 end
95
96                 cmd = cmd:lower()
97                 local meta = itemstack:get_meta()
98                 if cmd == "none" then
99                         meta:from_table(nil)
100                         worldedit.player_notify(name, "Brush assignment cleared.")
101                 else
102                         local cmddef = worldedit.registered_commands[cmd]
103                         if cmddef == nil or cmddef.require_pos ~= 1 then
104                                 worldedit.player_notify(name, "Invalid command for brush use: //" .. cmd)
105                                 return
106                         end
107
108                         -- Try parsing command params so we can give the user feedback
109                         local ok, err = cmddef.parse(params)
110                         if not ok then
111                                 err = err or "invalid usage"
112                                 worldedit.player_notify(name, "Brush command: " .. err)
113                                 return
114                         end
115
116                         meta:set_string("command", cmd)
117                         meta:set_string("params", params)
118                         local fullcmd = "//" .. cmd .. " " .. params
119                         meta:set_string("description",
120                                 minetest.registered_tools["worldedit:brush"].description .. ": " .. fullcmd)
121                         worldedit.player_notify(name, "Brush assigned to command: " .. fullcmd)
122                 end
123                 minetest.get_player_by_name(name):set_wielded_item(itemstack)
124         end,
125 })