maxlight = default.LIGHT_MAX -- Maximum light to grow
}
+Screwdriver API
+---------------
+The screwdriver API allows you to control a node's behaviour when a screwdriver is used on it.
+To use it, add the on_screwdriver function to the node definition.
+on_rotate(pos, node, user, mode, new_param2)
+^ pos: position of the node that the screwdriver is being used on
+^ node: that node
+^ user: the player who used the screwdriver
+^ mode: screwdriver.ROTATE_FACE or screwdriver.ROTATE_AXIS
+^ new_param2: the new value of param2 that would have been set if on_rotate wasn't there
+^ return value: false to disallow rotation, nil to keep default behaviour, true to allow
+ it but to indicate that changed have already been made (so the screwdriver will wear out)
+^ use on_rotate = screwdriver.disallow to always disallow rotation
+^ use on_rotate = screwdriver.rotate_simple to allow only face rotation
+
Stairs API
----------
The stairs API lets you register stairs and slabs and ensures that they are registered the same way as those
return true
end
local dir = minetest.facedir_to_dir(n.param2)
- local p = {x=pos.x+dir.x,y=pos.y,z=pos.z+dir.z}
+ local p = vector.add(pos, dir)
local n2 = minetest.get_node_or_nil(p)
- local def = minetest.registered_items[n2.name] or nil
- if not n2 or not def or not def.buildable_to then
+ local def = n2 and minetest.registered_items[n2.name]
+ if not def or not def.buildable_to then
minetest.remove_node(pos)
return true
end
local n = minetest.get_node_or_nil(pos)
if not n then return end
local dir = minetest.facedir_to_dir(n.param2)
- local p = {x=pos.x+dir.x,y=pos.y,z=pos.z+dir.z}
+ local p = vector.add(pos, dir)
local n2 = minetest.get_node(p)
if minetest.get_item_group(n2.name, "bed") == 2 and n.param2 == n2.param2 then
minetest.remove_node(p)
on_rightclick = function(pos, node, clicker)
beds.on_rightclick(pos, clicker)
end,
+ on_rotate = function(pos, node, user, mode, new_param2)
+ local dir = minetest.facedir_to_dir(node.param2)
+ local p = vector.add(pos, dir)
+ local node2 = minetest.get_node_or_nil(p)
+ if not node2 or not minetest.get_item_group(node2.name, "bed") == 2 or
+ not node.param2 == node2.param2 then
+ return false
+ end
+ if minetest.is_protected(p, user:get_player_name()) then
+ minetest.record_protection_violation(p, user:get_player_name())
+ return false
+ end
+ if mode ~= screwdriver.ROTATE_FACE then
+ return false
+ end
+ local newp = vector.add(pos, minetest.facedir_to_dir(new_param2))
+ local node3 = minetest.get_node_or_nil(newp)
+ local def = node3 and minetest.registered_nodes[node3.name]
+ if not def or not def.buildable_to then
+ return false
+ end
+ if minetest.is_protected(newp, user:get_player_name()) then
+ minetest.record_protection_violation(newp, user:get_player_name())
+ return false
+ end
+ node.param2 = new_param2
+ minetest.swap_node(pos, node)
+ minetest.remove_node(p)
+ minetest.set_node(newp, {name = node.name:gsub("%_bottom", "_top"), param2 = new_param2})
+ return true
+ end,
})
minetest.register_node(name .. "_top", {
return meta:get_string("doors_owner") == pn
end
+ local function on_rotate(pos, node, dir, user, check_name, mode, new_param2)
+ if not check_player_priv(pos, user) then
+ return false
+ end
+ if mode ~= screwdriver.ROTATE_FACE then
+ return false
+ end
+
+ pos.y = pos.y + dir
+ if not minetest.get_node(pos).name == check_name then
+ return false
+ end
+ if minetest.is_protected(pos, user:get_player_name()) then
+ minetest.record_protection_violation(pos, user:get_player_name())
+ return false
+ end
+
+ local node2 = minetest.get_node(pos)
+ node2.param2 = (node2.param2 + 1) % 4
+ minetest.swap_node(pos, node2)
+
+ pos.y = pos.y - dir
+ node.param2 = (node.param2 + 1) % 4
+ minetest.swap_node(pos, node)
+ return true
+ end
+
minetest.register_node(name.."_b_1", {
tiles = {tb[2], tb[2], tb[2], tb[2], tb[1], tb[1].."^[transformfx"},
paramtype = "light",
end
end,
+ on_rotate = function(pos, node, user, mode, new_param2)
+ return on_rotate(pos, node, 1, user, name.."_t_1", mode)
+ end,
+
can_dig = check_player_priv,
sounds = def.sounds,
sunlight_propagates = def.sunlight,
end
end,
+ on_rotate = function(pos, node, user, mode, new_param2)
+ return on_rotate(pos, node, -1, user, name.."_b_1", mode)
+ end,
+
can_dig = check_player_priv,
sounds = def.sounds,
sunlight_propagates = def.sunlight,
end
end,
+ on_rotate = function(pos, node, user, mode, new_param2)
+ return on_rotate(pos, node, 1, user, name.."_t_2", mode)
+ end,
+
can_dig = check_player_priv,
sounds = def.sounds,
sunlight_propagates = def.sunlight,
end
end,
+ on_rotate = function(pos, node, user, mode, new_param2)
+ return on_rotate(pos, node, -1, user, name.."_b_2", mode)
+ end,
+
can_dig = check_player_priv,
sounds = def.sounds,
sunlight_propagates = def.sunlight,
minetest.set_node(pos, {name = newname, param1 = node.param1, param2 = node.param2})
end
+ def.on_rotate = screwdriver.rotate_simple
+
-- Common trapdoor configuration
def.drawtype = "nodebox"
def.paramtype = "light"
+screwdriver = {}
+
local function nextrange(x, max)
x = x + 1
if x > max then
return x
end
-local ROTATE_FACE = 1
-local ROTATE_AXIS = 2
+screwdriver.ROTATE_FACE = 1
+screwdriver.ROTATE_AXIS = 2
+screwdriver.disallow = function(pos, node, user, mode, new_param2)
+ return false
+end
+screwdriver.rotate_simple = function(pos, node, user, mode, new_param2)
+ if mode ~= screwdriver.ROTATE_FACE then
+ return false
+ end
+end
local USES = 200
-- Handles rotation
local node = minetest.get_node(pos)
local ndef = minetest.registered_nodes[node.name]
- if not ndef or not ndef.paramtype2 == "facedir" or
- (ndef.drawtype == "nodebox" and
- not ndef.node_box.type == "fixed") or
- node.param2 == nil then
- return
- end
-
- if ndef.can_dig and not ndef.can_dig(pos, user) then
- return
- end
-
- -- Set param2
+ -- Compute param2
local rotationPart = node.param2 % 32 -- get first 4 bits
local preservePart = node.param2 - rotationPart
-
local axisdir = math.floor(rotationPart / 4)
local rotation = rotationPart - axisdir * 4
- if mode == ROTATE_FACE then
+ if mode == screwdriver.ROTATE_FACE then
rotationPart = axisdir * 4 + nextrange(rotation, 3)
- elseif mode == ROTATE_AXIS then
+ elseif mode == screwdriver.ROTATE_AXIS then
rotationPart = nextrange(axisdir, 5) * 4
end
- node.param2 = preservePart + rotationPart
- minetest.swap_node(pos, node)
+ local new_param2 = preservePart + rotationPart
+ local should_rotate = true
+
+ if ndef and ndef.on_rotate then -- Node provides a handler, so let the handler decide instead if the node can be rotated
+ -- Copy pos and node because callback can modify it
+ local result = ndef.on_rotate(vector.new(pos),
+ {name = node.name, param1 = node.param1, param2 = node.param2},
+ user, mode)
+ if result == false then -- Disallow rotation
+ return
+ elseif result == true then
+ should_rotate = false
+ end
+ else
+ if not ndef or not ndef.paramtype2 == "facedir" or
+ (ndef.drawtype == "nodebox" and
+ not ndef.node_box.type == "fixed") or
+ node.param2 == nil then
+ return
+ end
+
+ if ndef.can_dig and not ndef.can_dig(pos, user) then
+ return
+ end
+ end
+
+ if should_rotate then
+ node.param2 = new_param2
+ minetest.swap_node(pos, node)
+ end
if not minetest.setting_getbool("creative_mode") then
itemstack:add_wear(65535 / (USES - 1))
description = "Screwdriver (left-click rotates face, right-click rotates axis)",
inventory_image = "screwdriver.png",
on_use = function(itemstack, user, pointed_thing)
- screwdriver_handler(itemstack, user, pointed_thing, ROTATE_FACE)
+ screwdriver_handler(itemstack, user, pointed_thing, screwdriver.ROTATE_FACE)
return itemstack
end,
on_place = function(itemstack, user, pointed_thing)
- screwdriver_handler(itemstack, user, pointed_thing, ROTATE_AXIS)
+ screwdriver_handler(itemstack, user, pointed_thing, screwdriver.ROTATE_AXIS)
return itemstack
end,
})