local minetest, nodecore = minetest, nodecore local registry = {} local registered_rotatables = {} -- Registered rotatable nodes will call this function when their `on_rightclick` -- is triggered instead of their default implementation. Can be overwritten. registry.custom_on_rightclick = function(pos, node, clicker, item_stack, pointed_thing) end local function register_rotatable(name, facedir_lookup) local def = minetest.registered_nodes[name] if not def then error("Unknown node '" .. name .. "'") end if def.paramtype2 ~= "facedir" then error("Node '" .. name .. "' must be 'facedir'") end def.on_rightclick = function(...) registry.custom_on_rightclick(...) end registered_rotatables[name] = { lookup = facedir_lookup } end registry.register_rotatable = register_rotatable -- Returns whether the specified `node` is rotatable by this mod. local function is_rotatable(node) local name = node and node.name or "" return not not registered_rotatables[name] end registry.is_rotatable = is_rotatable -- Fixes facedir for the specified `node` when rotated to `facedir`. -- * Returns `nil` if the node can't rotate this way. -- * Returns `facedir` when the node can rotate this way. -- * Returns another facedir when the node should rotate another equivalent way. local function fix_rotatable_facedir(node, facedir) local name = node and node.name or "" local entry = registered_rotatables[name] if not entry then return nil end if not entry.lookup then return facedir end return entry.lookup[facedir] end registry.fix_rotatable_facedir = fix_rotatable_facedir -------------------------------------------- -- Register rotatable nodes from NodeCore -- -------------------------------------------- local function nodecore_filtered_lookup(eq_func) local lookup = {} for i = 0, 23 do local facedir = nodecore.facedirs[i] for j = 0, #lookup - 1 do local other = nodecore.facedirs[lookup[j]] if eq_func(facedir, other) then lookup[i] = j; break end end lookup[i] = lookup[i] or i end return lookup end local LENS_FILTERED_LOOKUP = nodecore_filtered_lookup( function(a, b) return vector.equals(a.f, b.f) end) local PRISM_FILTERED_LOOKUP = nodecore_filtered_lookup( function(a, b) return vector.equals(a.f, b.r) and vector.equals(a.r, b.f) end) local PANEL_FILTERED_LOOKUP = nodecore_filtered_lookup( function(a, b) return vector.equals(a.f, b.r) and vector.equals(a.r, b.f) end) for _, lens_state in ipairs({ "", "_on", "_glow", "_glow_start" }) do register_rotatable("nc_optics:lens" .. lens_state, LENS_FILTERED_LOOKUP) end for _, prism_state in ipairs({ "", "_on", "_gated" }) do register_rotatable("nc_optics:prism" .. prism_state, PRISM_FILTERED_LOOKUP) end register_rotatable("nc_doors:panel_plank" , PANEL_FILTERED_LOOKUP) register_rotatable("nc_doors:panel_cobble", PANEL_FILTERED_LOOKUP) return registry