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