2012-03-05 19:21:26 +01:00
--register stoppers for movestones/pistons
2013-04-02 11:56:37 +02:00
mesecon.mvps_stoppers = { }
2014-01-03 11:04:19 +01:00
mesecon.on_mvps_move = { }
2012-03-05 19:21:26 +01:00
2014-11-22 15:42:22 +01:00
function mesecon . is_mvps_stopper ( node , pushdir , stack , stackid )
2012-12-26 22:54:28 +01:00
local get_stopper = mesecon.mvps_stoppers [ node.name ]
if type ( get_stopper ) == " function " then
get_stopper = get_stopper ( node , pushdir , stack , stackid )
end
2015-02-14 11:54:27 +01:00
if ( get_stopper ) then print ( node.name ) end
2012-12-26 22:54:28 +01:00
return get_stopper
2012-03-05 19:21:26 +01:00
end
2014-11-22 15:42:22 +01:00
function mesecon . register_mvps_stopper ( nodename , get_stopper )
2012-12-26 22:54:28 +01:00
if get_stopper == nil then
get_stopper = true
end
mesecon.mvps_stoppers [ nodename ] = get_stopper
2012-03-05 19:21:26 +01:00
end
2014-01-03 11:04:19 +01:00
-- Functions to be called on mvps movement
2014-11-22 15:42:22 +01:00
function mesecon . register_on_mvps_move ( callback )
2014-01-03 11:04:19 +01:00
mesecon.on_mvps_move [ # mesecon.on_mvps_move + 1 ] = callback
end
local function on_mvps_move ( moved_nodes )
for _ , callback in ipairs ( mesecon.on_mvps_move ) do
callback ( moved_nodes )
end
end
2014-11-22 15:42:22 +01:00
function mesecon . mvps_process_stack ( stack )
2012-12-26 22:54:28 +01:00
-- update mesecons for placed nodes ( has to be done after all nodes have been added )
for _ , n in ipairs ( stack ) do
2013-12-01 04:13:00 +01:00
mesecon.on_placenode ( n.pos , minetest.get_node ( n.pos ) )
2012-12-26 22:54:28 +01:00
end
end
2012-06-23 13:24:03 +02:00
2014-11-22 15:42:22 +01:00
function mesecon . mvps_get_stack ( pos , dir , maximum )
2012-12-26 22:54:28 +01:00
-- determine the number of nodes to be pushed
2013-04-02 11:56:37 +02:00
local np = { x = pos.x , y = pos.y , z = pos.z }
2012-12-26 22:54:28 +01:00
local nodes = { }
while true do
2013-12-01 04:13:00 +01:00
local nn = minetest.get_node_or_nil ( np )
2012-12-26 22:54:28 +01:00
if not nn or # nodes > maximum then
-- don't push at all, something is in the way (unloaded map or too many nodes)
2013-04-02 12:09:59 +02:00
return nil
2012-12-26 22:54:28 +01:00
end
if nn.name == " air "
2013-06-22 21:43:58 +02:00
or ( minetest.registered_nodes [ nn.name ]
and minetest.registered_nodes [ nn.name ] . liquidtype ~= " none " ) then --is liquid
2012-12-26 22:54:28 +01:00
break
end
table.insert ( nodes , { node = nn , pos = np } )
2014-11-22 15:42:22 +01:00
np = mesecon.addPosRule ( np , dir )
2012-12-26 22:54:28 +01:00
end
2013-04-02 11:56:37 +02:00
return nodes
end
2015-02-14 11:54:27 +01:00
function mesecon . mvps_push ( pos , dir , maximum )
return mesecon.mvps_push_or_pull ( pos , dir , dir , maximum )
end
function mesecon . mvps_pull_all ( pos , dir , maximum )
return mesecon.mvps_push_or_pull ( pos , vector.multiply ( dir , - 1 ) , dir , maximum )
end
function mesecon . mvps_push_or_pull ( pos , stackdir , movedir , maximum ) -- pos: pos of mvps; stackdir: direction of building the stack; movedir: direction of actual movement; maximum: maximum nodes to be pushed
local nodes = mesecon.mvps_get_stack ( pos , stackdir , maximum )
2012-12-26 22:54:28 +01:00
2013-04-02 12:09:59 +02:00
if not nodes then return end
2015-02-14 11:54:27 +01:00
-- determine if one of the nodes blocks the push / pull
2012-12-26 22:54:28 +01:00
for id , n in ipairs ( nodes ) do
2015-02-14 11:54:27 +01:00
if mesecon.is_mvps_stopper ( n.node , movedir , nodes , id ) then
2012-12-26 22:54:28 +01:00
return
2012-06-23 13:24:03 +02:00
end
2012-12-26 22:54:28 +01:00
end
-- remove all nodes
for _ , n in ipairs ( nodes ) do
2013-12-01 04:13:00 +01:00
n.meta = minetest.get_meta ( n.pos ) : to_table ( )
minetest.remove_node ( n.pos )
2012-12-26 22:54:28 +01:00
end
-- update mesecons for removed nodes ( has to be done after all nodes have been removed )
for _ , n in ipairs ( nodes ) do
mesecon.on_dignode ( n.pos , n.node )
end
-- add nodes
for _ , n in ipairs ( nodes ) do
2015-02-14 11:54:27 +01:00
local np = mesecon.addPosRule ( n.pos , movedir )
2013-12-01 04:13:00 +01:00
minetest.add_node ( np , n.node )
minetest.get_meta ( np ) : from_table ( n.meta )
2012-12-26 22:54:28 +01:00
end
2015-02-14 11:54:27 +01:00
2014-01-03 11:04:19 +01:00
local moved_nodes = { }
2014-11-22 15:42:22 +01:00
local oldstack = mesecon.tablecopy ( nodes )
2012-12-26 22:54:28 +01:00
for i in ipairs ( nodes ) do
2014-01-03 11:04:19 +01:00
moved_nodes [ i ] = { }
moved_nodes [ i ] . oldpos = nodes [ i ] . pos
2015-02-14 11:54:27 +01:00
nodes [ i ] . pos = mesecon.addPosRule ( nodes [ i ] . pos , movedir )
2014-01-03 11:04:19 +01:00
moved_nodes [ i ] . pos = nodes [ i ] . pos
moved_nodes [ i ] . node = nodes [ i ] . node
moved_nodes [ i ] . meta = nodes [ i ] . meta
2012-12-26 22:54:28 +01:00
end
2015-02-14 11:54:27 +01:00
2014-01-03 11:04:19 +01:00
on_mvps_move ( moved_nodes )
2012-12-26 22:54:28 +01:00
2013-04-02 11:56:37 +02:00
return true , nodes , oldstack
2012-12-26 22:54:28 +01:00
end
2014-11-22 15:42:22 +01:00
mesecon.register_on_mvps_move ( function ( moved_nodes )
2014-01-03 11:04:19 +01:00
for _ , n in ipairs ( moved_nodes ) do
mesecon.on_placenode ( n.pos , n.node )
2014-11-22 11:37:47 +01:00
mesecon.update_autoconnect ( n.pos )
2014-01-03 11:04:19 +01:00
end
end )
2014-11-22 15:42:22 +01:00
function mesecon . mvps_pull_single ( pos , dir ) -- pos: pos of mvps; direction: direction of pull (matches push direction for sticky pistons)
2014-11-29 15:08:37 +01:00
local np = mesecon.addPosRule ( pos , dir )
local nn = minetest.get_node ( np )
2012-12-26 22:54:28 +01:00
2013-06-22 21:43:58 +02:00
if ( ( not minetest.registered_nodes [ nn.name ] ) --unregistered node
or minetest.registered_nodes [ nn.name ] . liquidtype == " none " ) --non-liquid node
2015-02-14 11:54:27 +01:00
and not mesecon.is_mvps_stopper ( nn , dir , { { pos = np , node = nn } } , 1 ) then --non-stopper node
2013-12-01 04:13:00 +01:00
local meta = minetest.get_meta ( np ) : to_table ( )
minetest.remove_node ( np )
minetest.add_node ( pos , nn )
minetest.get_meta ( pos ) : from_table ( meta )
2012-12-26 22:54:28 +01:00
nodeupdate ( np )
nodeupdate ( pos )
mesecon.on_dignode ( np , nn )
2014-11-22 11:37:47 +01:00
mesecon.update_autoconnect ( np )
2014-01-03 11:04:19 +01:00
on_mvps_move ( { { pos = pos , oldpos = np , node = nn , meta = meta } } )
2012-12-26 22:54:28 +01:00
end
2012-12-27 20:38:12 +01:00
return { { pos = np , node = { param2 = 0 , name = " air " } } , { pos = pos , node = nn } }
2012-06-23 13:24:03 +02:00
end
2014-11-22 15:42:22 +01:00
function mesecon . mvps_move_objects ( pos , dir , nodestack )
2013-04-02 12:09:59 +02:00
local objects_to_move = { }
2013-04-02 11:56:37 +02:00
-- Move object at tip of stack
2014-11-22 15:42:22 +01:00
local pushpos = mesecon.addPosRule ( pos , -- get pos at tip of stack
2013-06-22 21:43:58 +02:00
{ x = dir.x * # nodestack ,
y = dir.y * # nodestack ,
z = dir.z * # nodestack } )
2013-04-02 11:56:37 +02:00
2013-12-01 04:13:00 +01:00
local objects = minetest.get_objects_inside_radius ( pushpos , 1 )
2013-04-02 11:56:37 +02:00
for _ , obj in ipairs ( objects ) do
2013-04-02 12:09:59 +02:00
table.insert ( objects_to_move , obj )
2013-04-02 11:56:37 +02:00
end
-- Move objects lying/standing on the stack (before it was pushed - oldstack)
if tonumber ( minetest.setting_get ( " movement_gravity " ) ) > 0 and dir.y == 0 then
-- If gravity positive and dir horizontal, push players standing on the stack
for _ , n in ipairs ( nodestack ) do
2014-11-22 15:42:22 +01:00
local p_above = mesecon.addPosRule ( n.pos , { x = 0 , y = 1 , z = 0 } )
2013-12-01 04:13:00 +01:00
local objects = minetest.get_objects_inside_radius ( p_above , 1 )
2013-04-02 11:56:37 +02:00
for _ , obj in ipairs ( objects ) do
2013-04-02 12:09:59 +02:00
table.insert ( objects_to_move , obj )
2013-04-02 11:56:37 +02:00
end
end
end
2013-04-02 12:09:59 +02:00
for _ , obj in ipairs ( objects_to_move ) do
2013-04-02 11:56:37 +02:00
local entity = obj : get_luaentity ( )
2015-02-14 11:54:27 +01:00
if not entity then
2014-11-22 15:42:22 +01:00
local np = mesecon.addPosRule ( obj : getpos ( ) , dir )
2013-06-22 21:43:58 +02:00
--move only if destination is not solid
2013-12-01 04:13:00 +01:00
local nn = minetest.get_node ( np )
2013-06-22 21:43:58 +02:00
if not ( ( not minetest.registered_nodes [ nn.name ] )
or minetest.registered_nodes [ nn.name ] . walkable ) then
2013-04-02 12:09:59 +02:00
obj : setpos ( np )
end
2013-04-02 11:56:37 +02:00
end
end
2012-06-23 13:24:03 +02:00
end
2015-02-14 05:58:36 +01:00
mesecon.register_mvps_stopper ( " doors:door_steel_b_1 " )
mesecon.register_mvps_stopper ( " doors:door_steel_t_1 " )
mesecon.register_mvps_stopper ( " doors:door_steel_b_2 " )
mesecon.register_mvps_stopper ( " doors:door_steel_t_2 " )
2014-11-22 15:42:22 +01:00
mesecon.register_mvps_stopper ( " default:chest_locked " )