Skip to content

Commit 2824562

Browse files
committedMay 14, 2015
Add screwdriver callbacks, and code them for doors and beds
1 parent 852b337 commit 2824562

File tree

4 files changed

+142
-25
lines changed

4 files changed

+142
-25
lines changed
 

‎game_api.txt

+15
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,21 @@ farming.register_plant(name, Plant definition)
144144
maxlight = default.LIGHT_MAX -- Maximum light to grow
145145
}
146146

147+
Screwdriver API
148+
---------------
149+
The screwdriver API allows you to control a node's behaviour when a screwdriver is used on it.
150+
To use it, add the on_screwdriver function to the node definition.
151+
on_rotate(pos, node, user, mode, new_param2)
152+
^ pos: position of the node that the screwdriver is being used on
153+
^ node: that node
154+
^ user: the player who used the screwdriver
155+
^ mode: screwdriver.ROTATE_FACE or screwdriver.ROTATE_AXIS
156+
^ new_param2: the new value of param2 that would have been set if on_rotate wasn't there
157+
^ return value: false to disallow rotation, nil to keep default behaviour, true to allow
158+
it but to indicate that changed have already been made (so the screwdriver will wear out)
159+
^ use on_rotate = screwdriver.disallow to always disallow rotation
160+
^ use on_rotate = screwdriver.rotate_simple to allow only face rotation
161+
147162
Stairs API
148163
----------
149164
The stairs API lets you register stairs and slabs and ensures that they are registered the same way as those

‎mods/beds/api.lua

+35-4
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ function beds.register_bed(name, def)
2626
return true
2727
end
2828
local dir = minetest.facedir_to_dir(n.param2)
29-
local p = {x=pos.x+dir.x,y=pos.y,z=pos.z+dir.z}
29+
local p = vector.add(pos, dir)
3030
local n2 = minetest.get_node_or_nil(p)
31-
local def = minetest.registered_items[n2.name] or nil
32-
if not n2 or not def or not def.buildable_to then
31+
local def = n2 and minetest.registered_items[n2.name]
32+
if not def or not def.buildable_to then
3333
minetest.remove_node(pos)
3434
return true
3535
end
@@ -40,7 +40,7 @@ function beds.register_bed(name, def)
4040
local n = minetest.get_node_or_nil(pos)
4141
if not n then return end
4242
local dir = minetest.facedir_to_dir(n.param2)
43-
local p = {x=pos.x+dir.x,y=pos.y,z=pos.z+dir.z}
43+
local p = vector.add(pos, dir)
4444
local n2 = minetest.get_node(p)
4545
if minetest.get_item_group(n2.name, "bed") == 2 and n.param2 == n2.param2 then
4646
minetest.remove_node(p)
@@ -49,6 +49,37 @@ function beds.register_bed(name, def)
4949
on_rightclick = function(pos, node, clicker)
5050
beds.on_rightclick(pos, clicker)
5151
end,
52+
on_rotate = function(pos, node, user, mode, new_param2)
53+
local dir = minetest.facedir_to_dir(node.param2)
54+
local p = vector.add(pos, dir)
55+
local node2 = minetest.get_node_or_nil(p)
56+
if not node2 or not minetest.get_item_group(node2.name, "bed") == 2 or
57+
not node.param2 == node2.param2 then
58+
return false
59+
end
60+
if minetest.is_protected(p, user:get_player_name()) then
61+
minetest.record_protection_violation(p, user:get_player_name())
62+
return false
63+
end
64+
if mode ~= screwdriver.ROTATE_FACE then
65+
return false
66+
end
67+
local newp = vector.add(pos, minetest.facedir_to_dir(new_param2))
68+
local node3 = minetest.get_node_or_nil(newp)
69+
local def = node3 and minetest.registered_nodes[node3.name]
70+
if not def or not def.buildable_to then
71+
return false
72+
end
73+
if minetest.is_protected(newp, user:get_player_name()) then
74+
minetest.record_protection_violation(newp, user:get_player_name())
75+
return false
76+
end
77+
node.param2 = new_param2
78+
minetest.swap_node(pos, node)
79+
minetest.remove_node(p)
80+
minetest.set_node(newp, {name = node.name:gsub("%_bottom", "_top"), param2 = new_param2})
81+
return true
82+
end,
5283
})
5384

5485
minetest.register_node(name .. "_top", {

‎mods/doors/init.lua

+45
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,33 @@ function doors.register_door(name, def)
163163
return meta:get_string("doors_owner") == pn
164164
end
165165

166+
local function on_rotate(pos, node, dir, user, check_name, mode, new_param2)
167+
if not check_player_priv(pos, user) then
168+
return false
169+
end
170+
if mode ~= screwdriver.ROTATE_FACE then
171+
return false
172+
end
173+
174+
pos.y = pos.y + dir
175+
if not minetest.get_node(pos).name == check_name then
176+
return false
177+
end
178+
if minetest.is_protected(pos, user:get_player_name()) then
179+
minetest.record_protection_violation(pos, user:get_player_name())
180+
return false
181+
end
182+
183+
local node2 = minetest.get_node(pos)
184+
node2.param2 = (node2.param2 + 1) % 4
185+
minetest.swap_node(pos, node2)
186+
187+
pos.y = pos.y - dir
188+
node.param2 = (node.param2 + 1) % 4
189+
minetest.swap_node(pos, node)
190+
return true
191+
end
192+
166193
minetest.register_node(name.."_b_1", {
167194
tiles = {tb[2], tb[2], tb[2], tb[2], tb[1], tb[1].."^[transformfx"},
168195
paramtype = "light",
@@ -190,6 +217,10 @@ function doors.register_door(name, def)
190217
end
191218
end,
192219

220+
on_rotate = function(pos, node, user, mode, new_param2)
221+
return on_rotate(pos, node, 1, user, name.."_t_1", mode)
222+
end,
223+
193224
can_dig = check_player_priv,
194225
sounds = def.sounds,
195226
sunlight_propagates = def.sunlight,
@@ -223,6 +254,10 @@ function doors.register_door(name, def)
223254
end
224255
end,
225256

257+
on_rotate = function(pos, node, user, mode, new_param2)
258+
return on_rotate(pos, node, -1, user, name.."_b_1", mode)
259+
end,
260+
226261
can_dig = check_player_priv,
227262
sounds = def.sounds,
228263
sunlight_propagates = def.sunlight,
@@ -256,6 +291,10 @@ function doors.register_door(name, def)
256291
end
257292
end,
258293

294+
on_rotate = function(pos, node, user, mode, new_param2)
295+
return on_rotate(pos, node, 1, user, name.."_t_2", mode)
296+
end,
297+
259298
can_dig = check_player_priv,
260299
sounds = def.sounds,
261300
sunlight_propagates = def.sunlight,
@@ -289,6 +328,10 @@ function doors.register_door(name, def)
289328
end
290329
end,
291330

331+
on_rotate = function(pos, node, user, mode, new_param2)
332+
return on_rotate(pos, node, -1, user, name.."_b_2", mode)
333+
end,
334+
292335
can_dig = check_player_priv,
293336
sounds = def.sounds,
294337
sunlight_propagates = def.sunlight,
@@ -392,6 +435,8 @@ function doors.register_trapdoor(name, def)
392435
minetest.set_node(pos, {name = newname, param1 = node.param1, param2 = node.param2})
393436
end
394437

438+
def.on_rotate = screwdriver.rotate_simple
439+
395440
-- Common trapdoor configuration
396441
def.drawtype = "nodebox"
397442
def.paramtype = "light"

‎mods/screwdriver/init.lua

+47-21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
screwdriver = {}
2+
13
local function nextrange(x, max)
24
x = x + 1
35
if x > max then
@@ -6,8 +8,16 @@ local function nextrange(x, max)
68
return x
79
end
810

9-
local ROTATE_FACE = 1
10-
local ROTATE_AXIS = 2
11+
screwdriver.ROTATE_FACE = 1
12+
screwdriver.ROTATE_AXIS = 2
13+
screwdriver.disallow = function(pos, node, user, mode, new_param2)
14+
return false
15+
end
16+
screwdriver.rotate_simple = function(pos, node, user, mode, new_param2)
17+
if mode ~= screwdriver.ROTATE_FACE then
18+
return false
19+
end
20+
end
1121
local USES = 200
1222

1323
-- Handles rotation
@@ -25,31 +35,47 @@ local function screwdriver_handler(itemstack, user, pointed_thing, mode)
2535

2636
local node = minetest.get_node(pos)
2737
local ndef = minetest.registered_nodes[node.name]
28-
if not ndef or not ndef.paramtype2 == "facedir" or
29-
(ndef.drawtype == "nodebox" and
30-
not ndef.node_box.type == "fixed") or
31-
node.param2 == nil then
32-
return
33-
end
34-
35-
if ndef.can_dig and not ndef.can_dig(pos, user) then
36-
return
37-
end
38-
39-
-- Set param2
38+
-- Compute param2
4039
local rotationPart = node.param2 % 32 -- get first 4 bits
4140
local preservePart = node.param2 - rotationPart
42-
4341
local axisdir = math.floor(rotationPart / 4)
4442
local rotation = rotationPart - axisdir * 4
45-
if mode == ROTATE_FACE then
43+
if mode == screwdriver.ROTATE_FACE then
4644
rotationPart = axisdir * 4 + nextrange(rotation, 3)
47-
elseif mode == ROTATE_AXIS then
45+
elseif mode == screwdriver.ROTATE_AXIS then
4846
rotationPart = nextrange(axisdir, 5) * 4
4947
end
5048

51-
node.param2 = preservePart + rotationPart
52-
minetest.swap_node(pos, node)
49+
local new_param2 = preservePart + rotationPart
50+
local should_rotate = true
51+
52+
if ndef and ndef.on_rotate then -- Node provides a handler, so let the handler decide instead if the node can be rotated
53+
-- Copy pos and node because callback can modify it
54+
local result = ndef.on_rotate(vector.new(pos),
55+
{name = node.name, param1 = node.param1, param2 = node.param2},
56+
user, mode)
57+
if result == false then -- Disallow rotation
58+
return
59+
elseif result == true then
60+
should_rotate = false
61+
end
62+
else
63+
if not ndef or not ndef.paramtype2 == "facedir" or
64+
(ndef.drawtype == "nodebox" and
65+
not ndef.node_box.type == "fixed") or
66+
node.param2 == nil then
67+
return
68+
end
69+
70+
if ndef.can_dig and not ndef.can_dig(pos, user) then
71+
return
72+
end
73+
end
74+
75+
if should_rotate then
76+
node.param2 = new_param2
77+
minetest.swap_node(pos, node)
78+
end
5379

5480
if not minetest.setting_getbool("creative_mode") then
5581
itemstack:add_wear(65535 / (USES - 1))
@@ -63,11 +89,11 @@ minetest.register_tool("screwdriver:screwdriver", {
6389
description = "Screwdriver (left-click rotates face, right-click rotates axis)",
6490
inventory_image = "screwdriver.png",
6591
on_use = function(itemstack, user, pointed_thing)
66-
screwdriver_handler(itemstack, user, pointed_thing, ROTATE_FACE)
92+
screwdriver_handler(itemstack, user, pointed_thing, screwdriver.ROTATE_FACE)
6793
return itemstack
6894
end,
6995
on_place = function(itemstack, user, pointed_thing)
70-
screwdriver_handler(itemstack, user, pointed_thing, ROTATE_AXIS)
96+
screwdriver_handler(itemstack, user, pointed_thing, screwdriver.ROTATE_AXIS)
7197
return itemstack
7298
end,
7399
})

0 commit comments

Comments
 (0)
Please sign in to comment.