Files
lwcomponents/movefloor.lua
2021-11-06 21:46:50 +10:00

200 lines
4.4 KiB
Lua

local utils = ...
local S = utils.S
if utils.mesecon_supported and mesecon.mvps_push then
local mesecon_rules =
{
{ x = 1, y = 1, z = 0 },
{ x = -1, y = 1, z = 0 },
{ x = 0, y = 1, z = 1 },
{ x = 0, y = 1, z = -1 },
{ x = 1, y = -1, z = 0 },
{ x = -1, y = -1, z = 0 },
{ x = 0, y = -1, z = 1 },
{ x = 0, y = -1, z = -1 },
}
-- use mesecons movestone settings
local timer_interval = 1 / mesecon.setting ("movestone_speed", 3)
local max_push = 3
local max_pull = 3
-- helper functions:
local function get_movefloor_direction (rulename)
if rulename.y > 0 then
return { x = 0, y = 1, z = 0 }
elseif rulename.y < 0 then
return { x = 0, y = -1, z = 0 }
end
end
local function add_movefloor_list (pos, list)
for i = 1, #list do
if list[i].x == pos.x and
list[i].y == pos.y and
list[i].z == pos.z then
return false
end
end
list[#list + 1] = { x = pos.x, y = pos.y, z = pos.z }
return true
end
local function find_adjoining_movefloor (pos, list)
local tpos =
{
{ x = pos.x + 1, y = pos.y, z = pos.z },
{ x = pos.x - 1, y = pos.y, z = pos.z },
{ x = pos.x, y = pos.y, z = pos.z + 1 },
{ x = pos.x, y = pos.y, z = pos.z - 1 }
}
for i = 1, #tpos do
local node = minetest.get_node (tpos[i])
if node and node.name == "lwcomponents:movefloor" then
if add_movefloor_list (tpos[i], list) then
find_adjoining_movefloor (tpos[i], list)
end
end
end
end
-- copied from mesecons movestone
local function movefloor_move (pos, node, rulename, is_sticky)
local direction = get_movefloor_direction (rulename)
local play_sound = false
local list =
{
{ x = pos.x, y = pos.y, z = pos.z }
}
find_adjoining_movefloor (pos, list)
for i = 1, #list do
local frontpos = vector.add (list[i], direction)
local meta = minetest.get_meta (list[i])
local owner = meta:get_string ("owner")
local continue = true
-- ### Step 1: Push nodes in front ###
local success, stack, oldstack = mesecon.mvps_push (frontpos, direction, max_push, owner)
if not success then
if stack == "protected" then
meta:set_string ("infotext", "Can't move: protected area on the way")
else
minetest.get_node_timer (list[i]):start (timer_interval)
continue = false
end
end
if continue then
mesecon.mvps_move_objects (frontpos, direction, oldstack)
-- ### Step 2: Move the movestone ###
minetest.set_node (frontpos, node)
local meta2 = minetest.get_meta (frontpos)
meta2:set_string ("owner", owner)
minetest.remove_node (list[i])
mesecon.on_dignode (list[i], node)
mesecon.on_placenode (frontpos, node)
minetest.get_node_timer (frontpos):start (timer_interval)
play_sound = true
-- ### Step 3: If sticky, pull stack behind ###
if is_sticky and direction.y < 0 then
local backpos = vector.subtract (list[i], direction)
success, stack, oldstack = mesecon.mvps_pull_all (backpos, direction, max_pull, owner)
if success then
mesecon.mvps_move_objects (backpos, vector.multiply (direction, -1), oldstack, -1)
end
end
-- ### Step 4: Let things fall ###
minetest.check_for_falling (vector.add (list[i], { x = 0, y = 1, z = 0 }))
end
end
if play_sound then
minetest.sound_play("movestone", { pos = list[i], max_hear_distance = 20, gain = 0.5 }, true)
end
end
local function on_timer (pos, elapsed)
local sourcepos = mesecon.is_powered (pos)
if not sourcepos then
return
end
local rulename = vector.subtract (sourcepos[1], pos)
mesecon.activate (pos, minetest.get_node (pos), rulename, 0)
end
local function mesecon_support ()
return
{
effector =
{
rules = table.copy (mesecon_rules),
action_on = function (pos, node, rulename)
-- do something to turn the effector on
if rulename and not minetest.get_node_timer (pos):is_started () then
movefloor_move (pos, node, rulename, true)
end
end
}
}
end
minetest.register_node("lwcomponents:movefloor", {
description = S("Moving Floor"),
tiles = { "lwmovefloortop.png", "lwmovefloortop.png",
"lwmovefloorside.png", "lwmovefloorside.png",
"lwmovefloorside.png", "lwmovefloorside.png" },
sunlight_propagates = false,
drawtype = "normal",
node_box = {
type = "fixed",
fixed = {
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
}
},
groups = { cracky = 2 },
sounds = default.node_sound_wood_defaults (),
mesecons = mesecon_support (),
on_timer = on_timer,
})
end