Merge branch 'kay27_mechanics' as a squash

This commit is contained in:
kay27 2020-11-14 01:59:03 +04:00
parent bd2d0f717a
commit 2b1d21a5b5
5 changed files with 361 additions and 163 deletions

@ -1,6 +1,8 @@
-- Some global variables (don't overwrite them!)
mcl_vars = {}
mcl_vars.redstone_tick = 0.1
--- GUI / inventory menu settings
mcl_vars.gui_slots = "listcolors[#9990;#FFF7;#FFF0;#000;#FFF]"
-- nonbg is added as formspec prepend in mcl_formspec_prepend
@ -126,5 +128,3 @@ minetest.craftitemdef_default.stack_max = 64
-- Set random seed for all other mods (Remember to make sure no other mod calls this function)
math.randomseed(os.time())

@ -1,5 +1,13 @@
local S = minetest.get_translator("mcl_observers")
mcl_observers = {}
-- Warning! TODO: Remove this message.
-- 'realtime' is experimental feature! It can slow down the everything!
-- Please set it to false and restart the game if something's wrong:
local realtime = true
--local realtime = false
local rules_flat = {
{ x = 0, y = 0, z = -1, spread = true },
}
@ -14,6 +22,26 @@ end
local rules_down = {{ x = 0, y = 1, z = 0, spread = true }}
local rules_up = {{ x = 0, y = -1, z = 0, spread = true }}
function mcl_observers.observer_activate(pos)
minetest.after(mcl_vars.redstone_tick, function(pos)
node = minetest.get_node(pos)
if not node then
return
end
local nn = node.name
if nn == "mcl_observers:observer_off" then
minetest.set_node(pos, {name = "mcl_observers:observer_on", param2 = node.param2})
mesecon.receptor_on(pos, get_rules_flat(node))
elseif nn == "mcl_observers:observer_down_off" then
minetest.set_node(pos, {name = "mcl_observers:observer_down_on"})
mesecon.receptor_on(pos, rules_down)
elseif nn == "mcl_observers:observer_up_off" then
minetest.set_node(pos, {name = "mcl_observers:observer_up_on"})
mesecon.receptor_on(pos, rules_up)
end
end, {x=pos.x, y=pos.y, z=pos.z})
end
-- Scan the node in front of the observer
-- and update the observer state if needed.
-- TODO: Also scan metadata changes.
@ -34,7 +62,7 @@ local observer_scan = function(pos, initialize)
local oldparam2 = meta:get_string("node_param2")
local meta_needs_updating = false
if oldnode ~= "" and not initialize then
if not (frontnode.name == oldnode and frontnode.param2) then
if not (frontnode.name == oldnode and tostring(frontnode.param2) == oldparam2) then
-- Node state changed! Activate observer
if node.name == "mcl_observers:observer_off" then
minetest.set_node(pos, {name = "mcl_observers:observer_on", param2 = node.param2})
@ -53,7 +81,7 @@ local observer_scan = function(pos, initialize)
end
if meta_needs_updating then
meta:set_string("node_name", frontnode.name)
meta:set_string("node_param2", frontnode.param2)
meta:set_string("node_param2", tostring(frontnode.param2))
end
return frontnode
end
@ -102,7 +130,9 @@ mesecon.register_node("mcl_observers:observer",
rules = get_rules_flat,
}},
on_construct = function(pos)
observer_scan(pos, true)
if not realtime then
observer_scan(pos, true)
end
end,
after_place_node = observer_orientate,
},
@ -122,8 +152,7 @@ mesecon.register_node("mcl_observers:observer",
-- VERY quickly disable observer after construction
on_construct = function(pos)
local timer = minetest.get_node_timer(pos)
-- 1 redstone tick = 0.1 seconds
timer:start(0.1)
timer:start(mcl_vars.redstone_tick)
end,
on_timer = function(pos, elapsed)
local node = minetest.get_node(pos)
@ -154,7 +183,9 @@ mesecon.register_node("mcl_observers:observer_down",
rules = rules_down,
}},
on_construct = function(pos)
observer_scan(pos, true)
if not realtime then
observer_scan(pos, true)
end
end,
},
{
@ -172,8 +203,7 @@ mesecon.register_node("mcl_observers:observer_down",
-- VERY quickly disable observer after construction
on_construct = function(pos)
local timer = minetest.get_node_timer(pos)
-- 1 redstone tick = 0.1 seconds
timer:start(0.1)
timer:start(mcl_vars.redstone_tick)
end,
on_timer = function(pos, elapsed)
local node = minetest.get_node(pos)
@ -203,7 +233,9 @@ mesecon.register_node("mcl_observers:observer_up",
rules = rules_up,
}},
on_construct = function(pos)
observer_scan(pos, true)
if not realtime then
observer_scan(pos, true)
end
end,
},
{
@ -221,8 +253,7 @@ mesecon.register_node("mcl_observers:observer_up",
-- VERY quickly disable observer after construction
on_construct = function(pos)
local timer = minetest.get_node_timer(pos)
-- 1 redstone tick = 0.1 seconds
timer:start(0.1)
timer:start(mcl_vars.redstone_tick)
end,
on_timer = function(pos, elapsed)
minetest.set_node(pos, {name = "mcl_observers:observer_up_off"})
@ -230,22 +261,6 @@ mesecon.register_node("mcl_observers:observer_up",
end,
})
-- Regularily check the observer nodes.
-- TODO: This is rather slow and clunky. Find a more efficient way to do this.
minetest.register_abm({
label = "Observer node check",
nodenames = {"mcl_observers:observer_off", "mcl_observers:observer_down_off", "mcl_observers:observer_up_off"},
interval = 1,
chance = 1,
action = function(pos, node)
observer_scan(pos)
end,
})
minetest.register_craft({
output = "mcl_observers:observer_off",
recipe = {
@ -263,3 +278,154 @@ minetest.register_craft({
}
})
if realtime then
-- Override basic functions for observing:
mcl_observers.add_node = minetest.add_node
mcl_observers.set_node = minetest.set_node
mcl_observers.swap_node = minetest.swap_node
mcl_observers.remove_node = minetest.remove_node
minetest.add_node=function(pos,node)
mcl_observers.add_node(pos,node)
local n=minetest.get_node({x=pos.x+1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==-1 then
mcl_observers.observer_activate({x=pos.x+1,y=pos.y,z=pos.z})
end
n=minetest.get_node({x=pos.x-1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==1 then
mcl_observers.observer_activate({x=pos.x-1,y=pos.y,z=pos.z})
end
n=minetest.get_node({x=pos.x,y=pos.y,z=pos.z-1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==-1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z+1})
end
n=minetest.get_node({x=pos.x,y=pos.y,z=pos.z+1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z-1})
end
n=minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_u" then
mcl_observers.observer_activate({x=pos.x,y=pos.y-1,z=pos.z})
end
n=minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_d" then
mcl_observers.observer_activate({x=pos.x,y=pos.y+1,z=pos.z})
end
end
minetest.set_node=function(pos,node)
mcl_observers.set_node(pos,node)
local n=minetest.get_node({x=pos.x+1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==-1 then
mcl_observers.observer_activate({x=pos.x+1,y=pos.y,z=pos.z})
end
n=minetest.get_node({x=pos.x-1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==1 then
mcl_observers.observer_activate({x=pos.x-1,y=pos.y,z=pos.z})
end
n=minetest.get_node({x=pos.x,y=pos.y,z=pos.z-1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==-1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z+1})
end
n=minetest.get_node({x=pos.x,y=pos.y,z=pos.z+1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z-1})
end
n=minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_u" then
mcl_observers.observer_activate({x=pos.x,y=pos.y-1,z=pos.z})
end
n=minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_d" then
mcl_observers.observer_activate({x=pos.x,y=pos.y+1,z=pos.z})
end
end
minetest.swap_node=function(pos,node)
mcl_observers.swap_node(pos,node)
local n=minetest.get_node({x=pos.x+1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==-1 then
mcl_observers.observer_activate({x=pos.x+1,y=pos.y,z=pos.z})
end
n=minetest.get_node({x=pos.x-1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==1 then
mcl_observers.observer_activate({x=pos.x-1,y=pos.y,z=pos.z})
end
n=minetest.get_node({x=pos.x,y=pos.y,z=pos.z-1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==-1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z+1})
end
n=minetest.get_node({x=pos.x,y=pos.y,z=pos.z+1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z-1})
end
n=minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_u" then
mcl_observers.observer_activate({x=pos.x,y=pos.y-1,z=pos.z})
end
n=minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_d" then
mcl_observers.observer_activate({x=pos.x,y=pos.y+1,z=pos.z})
end
end
minetest.remove_node=function(pos)
mcl_observers.remove_node(pos)
local n=minetest.get_node({x=pos.x+1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==-1 then
mcl_observers.observer_activate({x=pos.x+1,y=pos.y,z=pos.z})
end
n=minetest.get_node({x=pos.x-1,y=pos.y,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).x==1 then
mcl_observers.observer_activate({x=pos.x-1,y=pos.y,z=pos.z})
end
n=minetest.get_node({x=pos.x,y=pos.y,z=pos.z-1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==-1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z+1})
end
n=minetest.get_node({x=pos.x,y=pos.y,z=pos.z+1})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_o" and minetest.facedir_to_dir(n.param2).z==1 then
mcl_observers.observer_activate({x=pos.x,y=pos.y,z=pos.z-1})
end
n=minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_u" then
mcl_observers.observer_activate({x=pos.x,y=pos.y-1,z=pos.z})
end
n=minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z})
if n and n.name and string.sub(n.name,1,24)=="mcl_observers:observer_d" then
mcl_observers.observer_activate({x=pos.x,y=pos.y+1,z=pos.z})
end
end
else -- if realtime then ^^^ else:
minetest.register_abm({
label = "Observer node check",
nodenames = {"mcl_observers:observer_off", "mcl_observers:observer_down_off", "mcl_observers:observer_up_off"},
interval = 1,
chance = 1,
action = function(pos, node)
observer_scan(pos)
end,
})
end
--[[
With the following code the observer will detect loading of areas where it is placed.
We need to restore signal generated by it before the area was unloaded.
Observer movement and atomic clock (one observer watches another) fails without this often.
But it WILL cause wrong single signal for all other cases, and I hope it's nothing.
After all, why it can't detect the loading of areas, if we haven't a better solution...
]]
minetest.register_lbm({
name = "mcl_observers:activate_lbm",
nodenames = {
"mcl_observers:observer_off",
"mcl_observers:observer_down_off",
"mcl_observers:observer_up_off",
"mcl_observers:observer_on",
"mcl_observers:observer_down_on",
"mcl_observers:observer_up_on",
},
run_at_every_load = true,
action = function(pos)
minetest.after(1, mcl_observers.observer_activate, {x=pos.x, y=pos.y, z=pos.z})
end,
})

@ -6,6 +6,8 @@ mesecon.mvps_droppers = {}
mesecon.on_mvps_move = {}
mesecon.mvps_unmov = {}
local is_protected = minetest.is_protected
--- Objects (entities) that cannot be moved
function mesecon.register_mvps_unmov(objectname)
mesecon.mvps_unmov[objectname] = true;
@ -34,25 +36,13 @@ function mesecon.register_mvps_dropper(nodename, get_dropper)
end
-- Nodes that cannot be pushed / pulled by movestones, pistons
function mesecon.is_mvps_stopper(node, pushdir, stack, stackid)
function mesecon.is_mvps_stopper(node)
-- unknown nodes are always stoppers
if not minetest.registered_nodes[node.name] then
return true
end
local get_stopper = mesecon.mvps_stoppers[node.name]
if type (get_stopper) == "function" then
get_stopper = get_stopper(node, pushdir, stack, stackid)
end
return get_stopper
return mesecon.mvps_stoppers[node.name] or not minetest.registered_nodes[node.name]
end
function mesecon.register_mvps_stopper(nodename, get_stopper)
if get_stopper == nil then
get_stopper = true
end
mesecon.mvps_stoppers[nodename] = get_stopper
function mesecon.register_mvps_stopper(nodename)
mesecon.mvps_stoppers[nodename] = true
end
-- For nodes which ignore sticky sides.
@ -112,7 +102,31 @@ local function node_replaceable(name)
return false
end
function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
local function is_available(pos)
local n = minetest.get_node(pos)
if not n then
return false, n
end
local name = n.name
if name == "ignore" then
minetest.get_voxel_manip():read_from_map(pos, pos)
n = minetest.get_node(pos)
if not n then
return false, n
end
name = n.name
end
if name == "ignore" then
return false, n
end
if minetest.registered_nodes[name] then
return minetest.registered_nodes[name].buildable_to, n or false, n
end
return false, n
end
function mesecon.mvps_get_stack(pos, dir, maximum, piston_pos)
-- determine the number of nodes to be pushed
local nodes = {}
local frontiers = {pos}
@ -124,8 +138,13 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
minetest.get_voxel_manip():read_from_map(np, np)
nn = minetest.get_node(np)
end
if mesecon.is_mvps_stopper(nn) then
return
end
if not node_replaceable(nn.name) then
if #nodes >= maximum then return nil end
if #nodes >= maximum then return nil, false end
table.insert(nodes, {node = nn, pos = np})
-- add connected nodes to frontiers, connected is a vector list
@ -133,30 +152,14 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
local connected = {}
if minetest.registered_nodes[nn.name]
and minetest.registered_nodes[nn.name].mvps_sticky then
connected = minetest.registered_nodes[nn.name].mvps_sticky(np, nn)
connected, has_loop = minetest.registered_nodes[nn.name].mvps_sticky(np, nn, piston_pos)
if has_loop then
return {}, true
end
end
table.insert(connected, vector.add(np, dir))
-- If adjacent node is sticky block and connects add that
-- position to the connected table
for _, r in ipairs(mesecon.rules.alldirs) do
local adjpos = vector.add(np, r)
local adjnode = minetest.get_node(adjpos)
if minetest.registered_nodes[adjnode.name]
and minetest.registered_nodes[adjnode.name].mvps_sticky then
local sticksto = minetest.registered_nodes[adjnode.name]
.mvps_sticky(adjpos, adjnode)
-- connects to this position?
for _, link in ipairs(sticksto) do
if vector.equals(link, np) then
table.insert(connected, adjpos)
end
end
end
end
if all_pull_sticky then
table.insert(connected, vector.subtract(np, dir))
end
@ -175,7 +178,7 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
duplicate = true
end
end
if not duplicate then
if not duplicate and not mesecon.is_mvps_stopper(minetest.get_node(cp)) then
table.insert(frontiers, cp)
end
end
@ -183,34 +186,75 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
table.remove(frontiers, 1)
end
return nodes
return nodes, false
end
function mesecon.mvps_push(pos, dir, maximum)
return mesecon.mvps_push_or_pull(pos, dir, dir, maximum, nil, false)
function mesecon.mvps_set_owner(pos, placer)
local meta = minetest.get_meta(pos)
local owner = placer and placer.get_player_name and placer:get_player_name()
if owner and owner ~= "" then
meta:set_string("owner", owner)
else
meta:set_string("owner", "$unknown") -- to distinguish from older pistons
end
end
function mesecon.mvps_pull_all(pos, dir, maximum)
return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum, true, true)
local function are_protected(positions, player_name)
local name = player_name
for _, pos in pairs(positions) do
if is_protected(pos, name) then
return true
end
end
return false
end
function mesecon.mvps_pull_single(pos, dir, maximum)
return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum, nil, true)
function mesecon.mvps_push(pos, dir, maximum, player_name, piston_pos)
return mesecon.mvps_push_or_pull(pos, dir, dir, maximum, player_name, piston_pos)
end
function mesecon.mvps_pull_single(pos, dir, maximum, player_name, piston_pos)
return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum, player_name, piston_pos)
end
-- pos: pos of mvps; stackdir: direction of building the stack
-- movedir: direction of actual movement
-- maximum: maximum nodes to be pushed
-- all_pull_sticky: All nodes are sticky in the direction that they are pulled from
function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, all_pull_sticky)
local nodes = mesecon.mvps_get_stack(pos, movedir, maximum, all_pull_sticky)
function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, player_name, piston_pos)
local nodes, has_loop = mesecon.mvps_get_stack(pos, movedir, maximum, piston_pos)
if has_loop then
return false
end
if not nodes then return end
-- determine if one of the nodes blocks the push / pull
for id, n in ipairs(nodes) do
if mesecon.is_mvps_stopper(n.node, movedir, nodes, id) then
local newpos={}
-- check node availability to push/pull into, and fill newpos[i]
for i in ipairs(nodes) do
newpos[i] = vector.add(nodes[i].pos, movedir)
if (newpos[i].x == piston_pos.x) and (newpos[i].y == piston_pos.y) and (newpos[i].z == piston_pos.z) then
return
end
if not is_available(newpos[i]) then
local available = false
for j in ipairs(nodes) do
if i ~= j then
if (newpos[i].x == nodes[j].pos.x) and (newpos[i].y == nodes[j].pos.y) and (newpos[i].z == nodes[j].pos.z) then
available = true
break
end
end
end
if not available then
return
end
end
end
if are_protected(nodes, player_name) then
return
end
local first_dropper = nil
@ -223,6 +267,10 @@ function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, all_pull_sti
minetest.dig_node(n.pos)
else
minetest.remove_node(n.pos)
local node_timer = minetest.get_node_timer(n.pos)
if node_timer:is_started() then
n.node_timer = {node_timer:get_timeout(), node_timer:get_elapsed()}
end
end
if is_dropper then
first_dropper = id
@ -243,9 +291,16 @@ function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, all_pull_sti
if first_dropper and id >= first_dropper then
break
end
local np = vector.add(n.pos, movedir)
local np = newpos[id]
minetest.add_node(np, n.node)
minetest.get_meta(np):from_table(n.meta)
if n.node_timer then
minetest.get_node_timer(np):set(unpack(n.node_timer))
end
if string.find(n.node.name, "mcl_observers:observer") then
-- It also counts as a block update when the observer itself is moved by a piston (Wiki):
mcl_observers.observer_activate(np)
end
end
local moved_nodes = {}
@ -256,10 +311,11 @@ function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, all_pull_sti
end
moved_nodes[i] = {}
moved_nodes[i].oldpos = nodes[i].pos
nodes[i].pos = vector.add(nodes[i].pos, movedir)
nodes[i].pos = newpos[i]
moved_nodes[i].pos = nodes[i].pos
moved_nodes[i].node = nodes[i].node
moved_nodes[i].meta = nodes[i].meta
moved_nodes[i].node_timer = nodes[i].node_timer
end
on_mvps_move(moved_nodes)

@ -94,10 +94,11 @@ local piston_on = function (pos, node)
local dir = piston_get_direction(pistonspec.dir, node)
local np = vector.add(pos, dir)
local success, stack, oldstack = mesecon.mvps_push(np, dir, PISTON_MAXIMUM_PUSH)
local meta = minetest.get_meta(pos)
local success, stack, oldstack = mesecon.mvps_push(np, dir, PISTON_MAXIMUM_PUSH, meta:get_string("owner"), pos)
if success then
minetest.add_node(pos, {param2 = node.param2, name = pistonspec.onname})
minetest.add_node(np, {param2 = node.param2, name = pistonspec.pusher})
minetest.set_node(pos, {param2 = node.param2, name = pistonspec.onname})
minetest.set_node(np, {param2 = node.param2, name = pistonspec.pusher})
local below = minetest.get_node({x=np.x,y=np.y-1,z=np.z})
if below.name == "mcl_farming:soil" or below.name == "mcl_farming:soil_wet" then
minetest.set_node({x=np.x,y=np.y-1,z=np.z}, {name = "mcl_core:dirt"})
@ -116,16 +117,22 @@ local piston_off = function (pos, node)
local pistonspec = minetest.registered_nodes[node.name].mesecons_piston
minetest.add_node(pos, {param2 = node.param2, name = pistonspec.offname})
piston_remove_pusher (pos, node)
if not pistonspec.sticky then
return
end
if pistonspec.sticky then
local dir = piston_get_direction(pistonspec.dir, node)
local pullpos = vector.add(pos, vector.multiply(dir, 2))
local stack = mesecon.mvps_pull_single(pullpos, vector.multiply(dir, -1), PISTON_MAXIMUM_PUSH)
local dir = piston_get_direction(pistonspec.dir, node)
local pullpos = vector.add(pos, vector.multiply(dir, 2))
local meta = minetest.get_meta(pos)
local success, stack, oldstack = mesecon.mvps_pull_single(pullpos, vector.multiply(dir, -1), PISTON_MAXIMUM_PUSH, meta:get_string("owner"), pos)
if success then
mesecon.mvps_process_stack(pos, dir, stack)
end
end
local piston_orientate = function (pos, placer)
mesecon.mvps_set_owner(pos, placer)
-- not placed by player
if not placer then return end
@ -812,75 +819,18 @@ minetest.register_node("mesecons_pistons:piston_down_pusher_sticky", {
})
-- Register pushers as stoppers if they would be seperated from the piston
local piston_pusher_get_stopper = function (node, dir, stack, stackid)
if (stack[stackid + 1]
and stack[stackid + 1].node.name == minetest.registered_nodes[node.name].corresponding_piston
and stack[stackid + 1].node.param2 == node.param2)
or (stack[stackid - 1]
and stack[stackid - 1].node.name == minetest.registered_nodes[node.name].corresponding_piston
and stack[stackid - 1].node.param2 == node.param2) then
return false
end
return true
end
local piston_pusher_up_down_get_stopper = function (node, dir, stack, stackid)
if (stack[stackid + 1]
and stack[stackid + 1].node.name == minetest.registered_nodes[node.name].corresponding_piston)
or (stack[stackid - 1]
and stack[stackid - 1].node.name == minetest.registered_nodes[node.name].corresponding_piston) then
return false
end
return true
end
mesecon.register_mvps_stopper("mesecons_pistons:piston_pusher_normal", piston_pusher_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_pusher_sticky", piston_pusher_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_up_pusher_normal", piston_pusher_up_down_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_up_pusher_sticky", piston_pusher_up_down_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_down_pusher_normal", piston_pusher_up_down_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_down_pusher_sticky", piston_pusher_up_down_get_stopper)
-- Register pistons as stoppers if they would be seperated from the stopper
local piston_up_down_get_stopper = function (node, dir, stack, stackid)
if (stack[stackid + 1]
and stack[stackid + 1].node.name == minetest.registered_nodes[node.name].mesecons_piston.pusher)
or (stack[stackid - 1]
and stack[stackid - 1].node.name == minetest.registered_nodes[node.name].mesecons_piston.pusher) then
return false
end
return true
end
local piston_get_stopper = function (node, dir, stack, stackid)
local pistonspec = minetest.registered_nodes[node.name].mesecons_piston
dir = piston_get_direction(pistonspec.dir, node)
local pusherpos = vector.add(stack[stackid].pos, dir)
local pushernode = minetest.get_node(pusherpos)
if minetest.registered_nodes[node.name].mesecons_piston.pusher == pushernode.name then
for _, s in ipairs(stack) do
if vector.equals(s.pos, pusherpos) -- pusher is also to be pushed
and s.node.param2 == node.param2 then
return false
end
end
end
return true
end
mesecon.register_mvps_stopper("mesecons_pistons:piston_normal_on", piston_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_sticky_on", piston_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_up_normal_on", piston_up_down_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_up_sticky_on", piston_up_down_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_down_normal_on", piston_up_down_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_down_sticky_on", piston_up_down_get_stopper)
mesecon.register_mvps_stopper("mesecons_pistons:piston_pusher_normal")
mesecon.register_mvps_stopper("mesecons_pistons:piston_pusher_sticky")
mesecon.register_mvps_stopper("mesecons_pistons:piston_up_pusher_normal")
mesecon.register_mvps_stopper("mesecons_pistons:piston_up_pusher_sticky")
mesecon.register_mvps_stopper("mesecons_pistons:piston_down_pusher_normal")
mesecon.register_mvps_stopper("mesecons_pistons:piston_down_pusher_sticky")
mesecon.register_mvps_stopper("mesecons_pistons:piston_normal_on")
mesecon.register_mvps_stopper("mesecons_pistons:piston_sticky_on")
mesecon.register_mvps_stopper("mesecons_pistons:piston_up_normal_on")
mesecon.register_mvps_stopper("mesecons_pistons:piston_up_sticky_on")
mesecon.register_mvps_stopper("mesecons_pistons:piston_down_normal_on")
mesecon.register_mvps_stopper("mesecons_pistons:piston_down_sticky_on")
--craft recipes
minetest.register_craft({

@ -6,6 +6,7 @@ local on_rotate
if mod_screwdriver then
on_rotate = screwdriver.rotate_3way
end
local alldirs = {{x=0,y=0,z=1}, {x=1,y=0,z=0}, {x=0,y=0,z=-1}, {x=-1,y=0,z=0}, {x=0,y=-1,z=0}, {x=0,y=1,z=0}}
minetest.register_node("mcl_core:bone_block", {
description = S("Bone Block"),
@ -52,14 +53,39 @@ minetest.register_node("mcl_core:slimeblock", {
},
_mcl_blast_resistance = 0,
_mcl_hardness = 0,
mvps_sticky = function (pos, node)
mvps_sticky = function (pos, node, piston_pos)
local connected = {}
if mesecon.rules.alldirs then
for _, r in ipairs(mesecon.rules.alldirs) do
table.insert(connected, vector.add(pos, r))
for n, v in ipairs(alldirs) do
local neighbor_pos = vector.add(pos, v)
local neighbor_node = minetest.get_node(neighbor_pos)
if neighbor_node then
if neighbor_node.name == "ignore" then
minetest.get_voxel_manip():read_from_map(neighbor_pos, neighbor_pos)
neighbor_node = minetest.get_node(neighbor_pos)
end
local name = neighbor_node.name
if name ~= "air" and name ~= "ignore" then
local piston, piston_side, piston_up, piston_down = false, false, false, false
if name == "mesecons_pistons:piston_sticky_off" or name == "mesecons_pistons:piston_normal_off" then
piston, piston_side = true, true
elseif name == "mesecons_pistons:piston_up_sticky_off" or name == "mesecons_pistons:piston_up_normal_off" then
piston, piston_up = true, true
elseif name == "mesecons_pistons:piston_down_sticky_off" or name == "mesecons_pistons:piston_down_normal_off" then
piston, piston_down = true, true
end
if not( (piston_side and (n-1==neighbor_node.param2)) or (piston_up and (n==5)) or (piston_down and (n==6)) ) then
if piston and piston_pos then
if piston_pos.x == neighbor_pos.x and piston_pos.y == neighbor_pos.y and piston_pos.z == neighbor_pos.z then
-- Loopback to the same piston! Preventing unwanted behavior:
return {}, true
end
end
table.insert(connected, neighbor_pos)
end
end
end
end
return connected
return connected, false
end,
})