Rotate optics and doors from NodeCore with ease.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
3.2 KiB

local minetest, vector, math_rad, math_random
= minetest, vector, math.rad, math.random
local get_node_active_selection_box = nc_extended_rotating.utility.get_node_active_selection_box;
local TAU = math.pi * 2
local MOD_NAME = minetest.get_current_modname()
local ARROWS_FACE = MOD_NAME .. ":arrows_face"
local ARROWS_EDGE = MOD_NAME .. ":arrows_edge"
local ARROWS_CORNER = MOD_NAME .. ":arrows_corner"
local entities_per_player = {}
local function register_entity(name, mesh, rot_speed)
minetest.register_entity(name, {
initial_properties = {
visual = "mesh",
mesh = mesh,
textures = { "nc_extended_rotating_arrows.png^[opacity:192" },
use_texture_alpha = true,
pointable = false, -- Can't be interacted with.
static_save = false, -- Doesn't get saved.
automatic_rotate = math_rad(rot_speed), -- Rotation in degrees per second.
},
on_deactivate = function(self, removal)
if not self.player_name then return end
entities_per_player[self.player_name] = nil
end,
})
end
register_entity(ARROWS_FACE , "nc_extended_rotating_face.obj" , 120)
register_entity(ARROWS_EDGE , "nc_extended_rotating_edge.obj" , 60)
register_entity(ARROWS_CORNER, "nc_extended_rotating_corner.obj", 120)
minetest.register_on_leaveplayer(function(player, timed_out)
local name = player:get_player_name()
local arrows = entities_per_player[name]
if arrows then arrows.object:remove() end
end)
local entity = {}
function entity.update_entity_hint(player, state)
local name = player:get_player_name()
local arrows = entities_per_player[name]
if state then
if arrows then
if state.pos == arrows.prev_pos and state.axis == arrows.prev_axis and state.invert == arrows.prev_invert then
-- No changes were made, so skip creating a new entity.
return
else
-- Changes were made, delete the old entity.
-- We do this to avoid rotation interpolation from `set_rotation`.
arrows.object:remove()
arrows = nil
end
end
local ent, off
if state.mode == "face" then ent, off = ARROWS_FACE , state.axis / 1.85
elseif state.mode == "edge" then ent, off = ARROWS_EDGE , vector.new(0, 0, 0)
elseif state.mode == "corner" then ent, off = ARROWS_CORNER, state.axis / 2.65
end
local box = get_node_active_selection_box(state.node)
local max = box.max - box.min
local pos = state.pos + off:multiply(max)
local rot = vector.dir_to_rotation(state.axis)
rot.x = rot.x + (state.invert and -TAU/4 or TAU/4)
arrows = minetest.add_entity(pos, ent):get_luaentity()
arrows.object:set_properties({ visual_size = max })
arrows.object:set_rotation(rot)
arrows.player_name = name
arrows.prev_pos = state.pos
arrows.prev_axis = state.axis
arrows.prev_invert = state.invert
entities_per_player[name] = arrows
elseif arrows then
arrows.object:remove()
end
end
return entity