@ -1,25 +1,21 @@
local ipairs , ItemStack , minetest , vector , include , nodecore
= ipairs , ItemStack , minetest , vector , include , nodecore
local ipairs , ItemStack , vector , include , nodecore
= ipairs , ItemStack , vector , include , nodecore
rawset ( _G , " nc_extended_rotating " , { } )
nc_extended_rotating.hud = include ( " hud " )
nc_extended_rotating.registry = include ( " registry " )
nc_extended_rotating.rotate = include ( " rotate " )
nc_extended_rotating.utility = include ( " utility " ) -- Depends on `rotate`.
nc_extended_rotating.entity = include ( " entity " ) -- Depends on `utility`.
nc_extended_rotating.state = include ( " state " ) -- Depends on `registry`, `rotate` and `utility`.
nc_extended_rotating.utility = include ( " utility " ) -- Depends on `rotate`.
nc_extended_rotating.entity = include ( " entity " ) -- Depends on `utility`.
nc_extended_rotating.registry = include ( " registry " ) -- Depends on `rotate` and `state` (late).
nc_extended_rotating.state = include ( " state " ) -- Depends on `registry`, `rotate` and `utility`.
local update_entity_hint = nc_extended_rotating.entity . update_entity_hint
local update_player_hud = nc_extended_rotating.hud . update_player_hud
local is_rotatable = nc_extended_rotating.registry . is_rotatable
local register_rotatable = nc_extended_rotating.registry . register_rotatable ;
local rotate_node = nc_extended_rotating.rotate . rotate_node
local update_rotating_state = nc_extended_rotating.state . update_rotating_state
local get_rotating_state = nc_extended_rotating.state . get_rotating_state
-------------------------------------
-- Register Player Update Function --
-------------------------------------
-- TODO: Fix HUD showing rotation hint when we wouldn't / can't rotate.
-- TODO: Simplify registration and `on_rightclick` replacement into one call.
-- TODO: Add some more comments.
local update_rotating_state = nc_extended_rotating.state . update_rotating_state
local update_player_hud = nc_extended_rotating.hud . update_player_hud
local update_entity_hint = nc_extended_rotating.entity . update_entity_hint
nodecore.register_playerstep ( {
label = " nc_extended_rotating:update " ,
@ -30,106 +26,39 @@ nodecore.register_playerstep({
end ,
} )
-- Register rotatable nodes from NodeCore.
do
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 )
---------------------------------------
-- Register Rotatable NodeCore Nodes --
---------------------------------------
for _ , lens_state in ipairs ( { " " , " _on " , " _glow " , " _glow_start " } ) do
register_rotatable ( " nc_optics:lens " .. lens_state , nil , LENS_FILTERED_LOOKUP ) end
for _ , prism_state in ipairs ( { " " , " _on " , " _gated " } ) do
register_rotatable ( " nc_optics:prism " .. prism_state , nil , PRISM_FILTERED_LOOKUP ) end
local nodecore_filtered_lookup = nc_extended_rotating.utility . nodecore_filtered_lookup
local register_rotatable = nc_extended_rotating.registry . register_rotatable ;
-- Register all existing door panels.
nodecore.register_on_register_item ( {
retroactive = true ,
func = function ( name , def )
-- NOTE: This function is actually called BEFORE the item is registered with Minetest.
-- Because of this, looking up the node definition by name does not work.
name = name : gsub ( " ^: " , " " ) -- Fix for older versions of NodeCore.
if def.groups and def.groups . door_panel and ( not def.groups . door )
then register_rotatable ( name , def , PANEL_FILTERED_LOOKUP ) end
end ,
} )
end
-- Register lenses.
local LENS_FILTERED_LOOKUP = nodecore_filtered_lookup ( function ( a , b )
return vector.equals ( a.f , b.f ) end )
for _ , lens_state in ipairs ( { " " , " _on " , " _glow " , " _glow_start " } ) do
register_rotatable ( " nc_optics:lens " .. lens_state , nil , LENS_FILTERED_LOOKUP ) end
local function handle_rightclick ( pos , node , clicker )
local state = get_rotating_state ( clicker , pos , node )
if ( not state ) or ( not state.success ) then return end
rotate_node ( pos , node , state.facedir )
end
-- Register prisms.
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 )
for _ , prism_state in ipairs ( { " " , " _on " , " _gated " } ) do
register_rotatable ( " nc_optics:prism " .. prism_state , nil , PRISM_FILTERED_LOOKUP ) end
-- Replace `on_rightclick` of rotatable nodes from NodeCore.
do
local function replace_optics_on_rightclick ( name )
local def = minetest.registered_nodes [ name ]
def.on_rightclick = handle_rightclick
end
-- Panels can't have their `on_rightclick` overridden completely.
-- We need to call the default implementation when holding a "pin".
local function replace_panel_on_rightclick ( name , pin )
local def = minetest.registered_nodes [ name ]
local default_rightclick = def.on_rightclick
def.on_rightclick = function ( pos , node , clicker , item_stack , ... )
if nodecore.protection_test ( pos , clicker ) or ItemStack ( item_stack ) : get_name ( ) == pin
then return default_rightclick ( pos , node , clicker , item_stack , ... )
else return handle_rightclick ( pos , node , clicker )
end
-- Register all existing and to-be-registered door panels.
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 )
nodecore.register_on_register_item ( {
retroactive = true ,
func = function ( name , def )
-- This function is actually called BEFORE the item is registered with Minetest.
-- Because of this, looking up the node definition by name does not work.
-- Thankfully, the panel is registered before the door, and as such it already exists.
if def.groups and def.groups . door then
local panel = def.drop_in_place . name -- The panel version of the door.
local pin = def.drop_non_silktouch or def.drop -- Dropped item is the door's pin.
register_rotatable ( panel , nil , PANEL_FILTERED_LOOKUP ,
function ( _ , _ , _ , item_stack ) return ItemStack ( item_stack ) : get_name ( ) == pin end )
end
end
for _ , lens_state in ipairs ( { " " , " _on " , " _glow " , " _glow_start " } ) do
replace_optics_on_rightclick ( " nc_optics:lens " .. lens_state ) end
for _ , lens_state in ipairs ( { " " , " _on " , " _gated " } ) do
replace_optics_on_rightclick ( " nc_optics:prism " .. lens_state ) end
-- Replace `on_rightclick` for all existing doors' panels.
nodecore.register_on_register_item ( {
retroactive = true ,
func = function ( name , def )
if def.groups and def.groups . door then
local panel = def.drop_in_place . name -- The panel version of the door.
local pin = def.drop_non_silktouch or def.drop -- Dropped item is the door's pin.
replace_panel_on_rightclick ( panel , pin )
end
end ,
} )
end
-- Override `nc_scaling`'s default empty hand right-click behavior so we can use it
-- to rotate things when holding sneak, which doesn't trigger a node's `on_rightclick`.
local default_on_place = minetest.registered_items [ " " ] . on_place
minetest.registered_items [ " " ] . on_place = function ( item_stack , placer , pointed_thing , ... )
if pointed_thing.type == " node " then
-- Player must sneak in order for this to run.
-- Non-sneak is handled by node's `on_rightclick`.
if minetest.is_player ( placer ) and placer : get_player_control ( ) . sneak then
local pos = pointed_thing.under
local node = minetest.get_node ( pos )
if is_rotatable ( node ) then
handle_rightclick ( pos , node , placer )
return -- Skip default behavior.
end
end
end
-- Call the default function, so we can still get the "scaling" functionality.
default_on_place ( item_stack , placer , pointed_thing , ... )
end
end ,
} )