|
|
@ -1,21 +1,25 @@ |
|
|
|
local ipairs, ItemStack, vector, include, nodecore |
|
|
|
local ipairs, ItemStack, minetest, vector, include, nodecore |
|
|
|
= ipairs, ItemStack, vector, include, nodecore |
|
|
|
= ipairs, ItemStack, minetest, vector, include, nodecore |
|
|
|
|
|
|
|
|
|
|
|
rawset(_G, "nc_extended_rotating", {}) |
|
|
|
rawset(_G, "nc_extended_rotating", {}) |
|
|
|
nc_extended_rotating.hud = include("hud") |
|
|
|
nc_extended_rotating.hud = include("hud") |
|
|
|
|
|
|
|
nc_extended_rotating.registry = include("registry") |
|
|
|
nc_extended_rotating.rotate = include("rotate") |
|
|
|
nc_extended_rotating.rotate = include("rotate") |
|
|
|
nc_extended_rotating.utility = include("utility") -- Depends on `rotate`. |
|
|
|
nc_extended_rotating.utility = include("utility") -- Depends on `rotate`. |
|
|
|
nc_extended_rotating.entity = include("entity") -- Depends on `utility`. |
|
|
|
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`. |
|
|
|
nc_extended_rotating.state = include("state") -- Depends on `registry`, `rotate` and `utility`. |
|
|
|
|
|
|
|
|
|
|
|
------------------------------------- |
|
|
|
|
|
|
|
-- Register Player Update Function -- |
|
|
|
|
|
|
|
------------------------------------- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- 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. |
|
|
|
|
|
|
|
|
|
|
|
nodecore.register_playerstep({ |
|
|
|
nodecore.register_playerstep({ |
|
|
|
label = "nc_extended_rotating:update", |
|
|
|
label = "nc_extended_rotating:update", |
|
|
@ -26,39 +30,106 @@ nodecore.register_playerstep({ |
|
|
|
end, |
|
|
|
end, |
|
|
|
}) |
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
--------------------------------------- |
|
|
|
-- Register rotatable nodes from NodeCore. |
|
|
|
-- Register Rotatable NodeCore Nodes -- |
|
|
|
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 nodecore_filtered_lookup = nc_extended_rotating.utility.nodecore_filtered_lookup |
|
|
|
local LENS_FILTERED_LOOKUP = nodecore_filtered_lookup( |
|
|
|
local register_rotatable = nc_extended_rotating.registry.register_rotatable; |
|
|
|
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 lenses. |
|
|
|
for _, lens_state in ipairs({ "", "_on", "_glow", "_glow_start" }) do |
|
|
|
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 |
|
|
|
register_rotatable("nc_optics:lens" .. lens_state, nil, LENS_FILTERED_LOOKUP) end |
|
|
|
|
|
|
|
for _, prism_state in ipairs({ "", "_on", "_gated" }) do |
|
|
|
-- 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 |
|
|
|
register_rotatable("nc_optics:prism" .. prism_state, nil, PRISM_FILTERED_LOOKUP) end |
|
|
|
|
|
|
|
|
|
|
|
-- Register all existing and to-be-registered door panels. |
|
|
|
-- Register all existing door panels. |
|
|
|
local PANEL_FILTERED_LOOKUP = nodecore_filtered_lookup(function(a, b) |
|
|
|
nodecore.register_on_register_item({ |
|
|
|
return vector.equals(a.f, b.r) and vector.equals(a.r, b.f) end) |
|
|
|
|
|
|
|
nodecore.register_on_register_item({ |
|
|
|
|
|
|
|
retroactive = true, |
|
|
|
retroactive = true, |
|
|
|
func = function(name, def) |
|
|
|
func = function(name, def) |
|
|
|
-- This function is actually called BEFORE the item is registered with Minetest. |
|
|
|
-- 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. |
|
|
|
-- 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. |
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- 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 |
|
|
|
|
|
|
|
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 |
|
|
|
if def.groups and def.groups.door then |
|
|
|
local panel = def.drop_in_place.name -- The panel version of the door. |
|
|
|
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. |
|
|
|
local pin = def.drop_non_silktouch or def.drop -- Dropped item is the door's pin. |
|
|
|
register_rotatable(panel, nil, PANEL_FILTERED_LOOKUP, |
|
|
|
replace_panel_on_rightclick(panel, pin) |
|
|
|
function(_, _, _, item_stack) return ItemStack(item_stack):get_name() == pin end) |
|
|
|
|
|
|
|
end |
|
|
|
end |
|
|
|
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 |
|
|
|