1 if minetest.raycast == nil then
3 "worldedit_brush requires at least Minetest 5.0"
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()
12 local cmd = meta:get_string("command")
14 worldedit.player_notify(name,
15 "This brush is not bound, use //brush to bind a command to it.")
19 local cmddef = worldedit.registered_commands[cmd]
20 if cmddef == nil then return false end -- shouldn't happen as //brush checks this
22 local has_privs, missing_privs = minetest.check_player_privs(name, cmddef.privs)
24 worldedit.player_notify(name,
25 "Missing privileges: " .. table.concat(missing_privs, ", "))
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.")
39 assert(pointed_thing.type == "node")
40 worldedit.pos1[name] = pointed_thing.under
41 worldedit.pos2[name] = nil
42 worldedit.marker_update(name)
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)
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
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))
59 worldedit.player_notify = player_notify_old
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)
68 on_use = function(itemstack, placer, pointed_thing)
69 brush_on_use(itemstack, placer)
70 return itemstack -- nothing consumed, nothing changed
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+(.+)$")
82 found, _, cmd = param:find("^(.+)$")
87 return true, cmd, params
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.")
97 local meta = itemstack:get_meta()
100 worldedit.player_notify(name, "Brush assignment cleared.")
102 local cmddef = worldedit.registered_commands[cmd]
103 if cmddef == nil or cmddef.require_pos ~= 1 then
104 worldedit.player_notify(name, "//" .. cmd .. " cannot be used with brushes")
108 -- Try parsing command params so we can give the user feedback
109 local ok, err = cmddef.parse(params)
111 err = err or "invalid usage"
112 worldedit.player_notify(name, "Error with brush command: " .. err)
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)
123 minetest.get_player_by_name(name):set_wielded_item(itemstack)