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

View file

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

View file

@ -1,5 +1,13 @@
local S = minetest.get_translator("mcl_observers") 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 = { local rules_flat = {
{ x = 0, y = 0, z = -1, spread = true }, { 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_down = {{ x = 0, y = 1, z = 0, spread = true }}
local rules_up = {{ 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 -- Scan the node in front of the observer
-- and update the observer state if needed. -- and update the observer state if needed.
-- TODO: Also scan metadata changes. -- TODO: Also scan metadata changes.
@ -34,7 +62,7 @@ local observer_scan = function(pos, initialize)
local oldparam2 = meta:get_string("node_param2") local oldparam2 = meta:get_string("node_param2")
local meta_needs_updating = false local meta_needs_updating = false
if oldnode ~= "" and not initialize then 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 -- Node state changed! Activate observer
if node.name == "mcl_observers:observer_off" then if node.name == "mcl_observers:observer_off" then
minetest.set_node(pos, {name = "mcl_observers:observer_on", param2 = node.param2}) minetest.set_node(pos, {name = "mcl_observers:observer_on", param2 = node.param2})
@ -53,7 +81,7 @@ local observer_scan = function(pos, initialize)
end end
if meta_needs_updating then if meta_needs_updating then
meta:set_string("node_name", frontnode.name) meta:set_string("node_name", frontnode.name)
meta:set_string("node_param2", frontnode.param2) meta:set_string("node_param2", tostring(frontnode.param2))
end end
return frontnode return frontnode
end end
@ -102,7 +130,9 @@ mesecon.register_node("mcl_observers:observer",
rules = get_rules_flat, rules = get_rules_flat,
}}, }},
on_construct = function(pos) on_construct = function(pos)
if not realtime then
observer_scan(pos, true) observer_scan(pos, true)
end
end, end,
after_place_node = observer_orientate, after_place_node = observer_orientate,
}, },
@ -122,8 +152,7 @@ mesecon.register_node("mcl_observers:observer",
-- VERY quickly disable observer after construction -- VERY quickly disable observer after construction
on_construct = function(pos) on_construct = function(pos)
local timer = minetest.get_node_timer(pos) local timer = minetest.get_node_timer(pos)
-- 1 redstone tick = 0.1 seconds timer:start(mcl_vars.redstone_tick)
timer:start(0.1)
end, end,
on_timer = function(pos, elapsed) on_timer = function(pos, elapsed)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
@ -154,7 +183,9 @@ mesecon.register_node("mcl_observers:observer_down",
rules = rules_down, rules = rules_down,
}}, }},
on_construct = function(pos) on_construct = function(pos)
if not realtime then
observer_scan(pos, true) observer_scan(pos, true)
end
end, end,
}, },
{ {
@ -172,8 +203,7 @@ mesecon.register_node("mcl_observers:observer_down",
-- VERY quickly disable observer after construction -- VERY quickly disable observer after construction
on_construct = function(pos) on_construct = function(pos)
local timer = minetest.get_node_timer(pos) local timer = minetest.get_node_timer(pos)
-- 1 redstone tick = 0.1 seconds timer:start(mcl_vars.redstone_tick)
timer:start(0.1)
end, end,
on_timer = function(pos, elapsed) on_timer = function(pos, elapsed)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
@ -203,7 +233,9 @@ mesecon.register_node("mcl_observers:observer_up",
rules = rules_up, rules = rules_up,
}}, }},
on_construct = function(pos) on_construct = function(pos)
if not realtime then
observer_scan(pos, true) observer_scan(pos, true)
end
end, end,
}, },
{ {
@ -221,8 +253,7 @@ mesecon.register_node("mcl_observers:observer_up",
-- VERY quickly disable observer after construction -- VERY quickly disable observer after construction
on_construct = function(pos) on_construct = function(pos)
local timer = minetest.get_node_timer(pos) local timer = minetest.get_node_timer(pos)
-- 1 redstone tick = 0.1 seconds timer:start(mcl_vars.redstone_tick)
timer:start(0.1)
end, end,
on_timer = function(pos, elapsed) on_timer = function(pos, elapsed)
minetest.set_node(pos, {name = "mcl_observers:observer_up_off"}) minetest.set_node(pos, {name = "mcl_observers:observer_up_off"})
@ -230,22 +261,6 @@ mesecon.register_node("mcl_observers:observer_up",
end, 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({ minetest.register_craft({
output = "mcl_observers:observer_off", output = "mcl_observers:observer_off",
recipe = { 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,
})

View file

@ -6,6 +6,8 @@ mesecon.mvps_droppers = {}
mesecon.on_mvps_move = {} mesecon.on_mvps_move = {}
mesecon.mvps_unmov = {} mesecon.mvps_unmov = {}
local is_protected = minetest.is_protected
--- Objects (entities) that cannot be moved --- Objects (entities) that cannot be moved
function mesecon.register_mvps_unmov(objectname) function mesecon.register_mvps_unmov(objectname)
mesecon.mvps_unmov[objectname] = true; mesecon.mvps_unmov[objectname] = true;
@ -34,25 +36,13 @@ function mesecon.register_mvps_dropper(nodename, get_dropper)
end end
-- Nodes that cannot be pushed / pulled by movestones, pistons -- 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 -- unknown nodes are always stoppers
if not minetest.registered_nodes[node.name] then return mesecon.mvps_stoppers[node.name] or not minetest.registered_nodes[node.name]
return true
end end
local get_stopper = mesecon.mvps_stoppers[node.name] function mesecon.register_mvps_stopper(nodename)
if type (get_stopper) == "function" then mesecon.mvps_stoppers[nodename] = true
get_stopper = get_stopper(node, pushdir, stack, stackid)
end
return get_stopper
end
function mesecon.register_mvps_stopper(nodename, get_stopper)
if get_stopper == nil then
get_stopper = true
end
mesecon.mvps_stoppers[nodename] = get_stopper
end end
-- For nodes which ignore sticky sides. -- For nodes which ignore sticky sides.
@ -112,7 +102,31 @@ local function node_replaceable(name)
return false return false
end 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 -- determine the number of nodes to be pushed
local nodes = {} local nodes = {}
local frontiers = {pos} 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) minetest.get_voxel_manip():read_from_map(np, np)
nn = minetest.get_node(np) nn = minetest.get_node(np)
end end
if mesecon.is_mvps_stopper(nn) then
return
end
if not node_replaceable(nn.name) then 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}) table.insert(nodes, {node = nn, pos = np})
-- add connected nodes to frontiers, connected is a vector list -- 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 = {} local connected = {}
if minetest.registered_nodes[nn.name] if minetest.registered_nodes[nn.name]
and minetest.registered_nodes[nn.name].mvps_sticky then 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 end
table.insert(connected, vector.add(np, dir)) 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 if all_pull_sticky then
table.insert(connected, vector.subtract(np, dir)) table.insert(connected, vector.subtract(np, dir))
end end
@ -175,7 +178,7 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
duplicate = true duplicate = true
end end
end end
if not duplicate then if not duplicate and not mesecon.is_mvps_stopper(minetest.get_node(cp)) then
table.insert(frontiers, cp) table.insert(frontiers, cp)
end end
end end
@ -183,34 +186,75 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
table.remove(frontiers, 1) table.remove(frontiers, 1)
end end
return nodes return nodes, false
end end
function mesecon.mvps_push(pos, dir, maximum) function mesecon.mvps_set_owner(pos, placer)
return mesecon.mvps_push_or_pull(pos, dir, dir, maximum, nil, false) 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 end
function mesecon.mvps_pull_all(pos, dir, maximum) local function are_protected(positions, player_name)
return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum, true, true) local name = player_name
for _, pos in pairs(positions) do
if is_protected(pos, name) then
return true
end
end
return false
end end
function mesecon.mvps_pull_single(pos, dir, maximum) function mesecon.mvps_push(pos, dir, maximum, player_name, piston_pos)
return mesecon.mvps_push_or_pull(pos, vector.multiply(dir, -1), dir, maximum, nil, true) 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 end
-- pos: pos of mvps; stackdir: direction of building the stack -- pos: pos of mvps; stackdir: direction of building the stack
-- movedir: direction of actual movement -- movedir: direction of actual movement
-- maximum: maximum nodes to be pushed -- maximum: maximum nodes to be pushed
-- all_pull_sticky: All nodes are sticky in the direction that they are pulled from -- 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) function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, player_name, piston_pos)
local nodes = mesecon.mvps_get_stack(pos, movedir, maximum, all_pull_sticky) 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 if not nodes then return end
-- determine if one of the nodes blocks the push / pull
for id, n in ipairs(nodes) do local newpos={}
if mesecon.is_mvps_stopper(n.node, movedir, nodes, id) then -- 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 return
end 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 end
local first_dropper = nil 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) minetest.dig_node(n.pos)
else else
minetest.remove_node(n.pos) 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 end
if is_dropper then if is_dropper then
first_dropper = id 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 if first_dropper and id >= first_dropper then
break break
end end
local np = vector.add(n.pos, movedir) local np = newpos[id]
minetest.add_node(np, n.node) minetest.add_node(np, n.node)
minetest.get_meta(np):from_table(n.meta) 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 end
local moved_nodes = {} local moved_nodes = {}
@ -256,10 +311,11 @@ function mesecon.mvps_push_or_pull(pos, stackdir, movedir, maximum, all_pull_sti
end end
moved_nodes[i] = {} moved_nodes[i] = {}
moved_nodes[i].oldpos = nodes[i].pos 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].pos = nodes[i].pos
moved_nodes[i].node = nodes[i].node moved_nodes[i].node = nodes[i].node
moved_nodes[i].meta = nodes[i].meta moved_nodes[i].meta = nodes[i].meta
moved_nodes[i].node_timer = nodes[i].node_timer
end end
on_mvps_move(moved_nodes) on_mvps_move(moved_nodes)

View file

@ -94,10 +94,11 @@ local piston_on = function (pos, node)
local dir = piston_get_direction(pistonspec.dir, node) local dir = piston_get_direction(pistonspec.dir, node)
local np = vector.add(pos, dir) 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 if success then
minetest.add_node(pos, {param2 = node.param2, name = pistonspec.onname}) minetest.set_node(pos, {param2 = node.param2, name = pistonspec.onname})
minetest.add_node(np, {param2 = node.param2, name = pistonspec.pusher}) 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}) 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 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"}) 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 local pistonspec = minetest.registered_nodes[node.name].mesecons_piston
minetest.add_node(pos, {param2 = node.param2, name = pistonspec.offname}) minetest.add_node(pos, {param2 = node.param2, name = pistonspec.offname})
piston_remove_pusher (pos, node) 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 dir = piston_get_direction(pistonspec.dir, node)
local pullpos = vector.add(pos, vector.multiply(dir, 2)) local pullpos = vector.add(pos, vector.multiply(dir, 2))
local stack = mesecon.mvps_pull_single(pullpos, vector.multiply(dir, -1), PISTON_MAXIMUM_PUSH) 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) mesecon.mvps_process_stack(pos, dir, stack)
end end
end end
local piston_orientate = function (pos, placer) local piston_orientate = function (pos, placer)
mesecon.mvps_set_owner(pos, placer)
-- not placed by player -- not placed by player
if not placer then return end 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 mesecon.register_mvps_stopper("mesecons_pistons:piston_pusher_normal")
local piston_pusher_get_stopper = function (node, dir, stack, stackid) mesecon.register_mvps_stopper("mesecons_pistons:piston_pusher_sticky")
if (stack[stackid + 1] mesecon.register_mvps_stopper("mesecons_pistons:piston_up_pusher_normal")
and stack[stackid + 1].node.name == minetest.registered_nodes[node.name].corresponding_piston mesecon.register_mvps_stopper("mesecons_pistons:piston_up_pusher_sticky")
and stack[stackid + 1].node.param2 == node.param2) mesecon.register_mvps_stopper("mesecons_pistons:piston_down_pusher_normal")
or (stack[stackid - 1] mesecon.register_mvps_stopper("mesecons_pistons:piston_down_pusher_sticky")
and stack[stackid - 1].node.name == minetest.registered_nodes[node.name].corresponding_piston mesecon.register_mvps_stopper("mesecons_pistons:piston_normal_on")
and stack[stackid - 1].node.param2 == node.param2) then mesecon.register_mvps_stopper("mesecons_pistons:piston_sticky_on")
return false mesecon.register_mvps_stopper("mesecons_pistons:piston_up_normal_on")
end mesecon.register_mvps_stopper("mesecons_pistons:piston_up_sticky_on")
return true mesecon.register_mvps_stopper("mesecons_pistons:piston_down_normal_on")
end mesecon.register_mvps_stopper("mesecons_pistons:piston_down_sticky_on")
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)
--craft recipes --craft recipes
minetest.register_craft({ minetest.register_craft({

View file

@ -6,6 +6,7 @@ local on_rotate
if mod_screwdriver then if mod_screwdriver then
on_rotate = screwdriver.rotate_3way on_rotate = screwdriver.rotate_3way
end 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", { minetest.register_node("mcl_core:bone_block", {
description = S("Bone Block"), description = S("Bone Block"),
@ -52,14 +53,39 @@ minetest.register_node("mcl_core:slimeblock", {
}, },
_mcl_blast_resistance = 0, _mcl_blast_resistance = 0,
_mcl_hardness = 0, _mcl_hardness = 0,
mvps_sticky = function (pos, node) mvps_sticky = function (pos, node, piston_pos)
local connected = {} local connected = {}
if mesecon.rules.alldirs then for n, v in ipairs(alldirs) do
for _, r in ipairs(mesecon.rules.alldirs) do local neighbor_pos = vector.add(pos, v)
table.insert(connected, vector.add(pos, r)) 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
end end
return connected table.insert(connected, neighbor_pos)
end
end
end
end
return connected, false
end, end,
}) })