Skip to content
Snippets Groups Projects
Commit 2824562d authored by Novatux's avatar Novatux
Browse files

Add screwdriver callbacks, and code them for doors and beds

parent 852b3379
No related branches found
No related tags found
No related merge requests found
......@@ -144,6 +144,21 @@ farming.register_plant(name, Plant definition)
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
......
......@@ -26,10 +26,10 @@ function beds.register_bed(name, def)
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
......@@ -40,7 +40,7 @@ function beds.register_bed(name, def)
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)
......@@ -49,6 +49,37 @@ function beds.register_bed(name, def)
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", {
......
......@@ -163,6 +163,33 @@ function doors.register_door(name, def)
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",
......@@ -190,6 +217,10 @@ function doors.register_door(name, def)
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,
......@@ -223,6 +254,10 @@ function doors.register_door(name, def)
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,
......@@ -256,6 +291,10 @@ function doors.register_door(name, def)
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,
......@@ -289,6 +328,10 @@ function doors.register_door(name, def)
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,
......@@ -392,6 +435,8 @@ function doors.register_trapdoor(name, def)
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
......@@ -6,8 +8,16 @@ local function nextrange(x, max)
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
......@@ -25,31 +35,47 @@ local function screwdriver_handler(itemstack, user, pointed_thing, mode)
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))
......@@ -63,11 +89,11 @@ minetest.register_tool("screwdriver:screwdriver", {
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,
})
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment