Consider connect_sides for item transport

Previously connect_sides was only used to choose the correct visual
model, but not during item transport. This allowed items to exit tubes
in directions without a visual connection and enter objects from sides
that should not be connectable according to connect_sides.
For example an item could enter a chest from the front, if a tube passed
there.

This change saves the connect_sides in the meta table of the object
whenever the visual representation is updated. When nothing is cached
yet, it uses the old behavior. That way it does not break existing
builds.
This commit is contained in:
Alexander Ried 2020-06-22 06:41:30 +00:00 committed by groxxda
parent 9338c109a6
commit c79e68a80c
2 changed files with 14 additions and 10 deletions

@ -53,27 +53,28 @@ local function tube_autoroute(pos)
} }
-- xm = 1, xp = 2, ym = 3, yp = 4, zm = 5, zp = 6 -- xm = 1, xp = 2, ym = 3, yp = 4, zm = 5, zp = 6
local positions = {} local adjlist = {} -- this will be used in item_transport
local nodes = {}
for i, adj in ipairs(adjustments) do for i, adj in ipairs(adjustments) do
positions[i] = vector.add(pos, adj) local position = vector.add(pos, adj)
nodes[i] = minetest.get_node(positions[i]) local node = minetest.get_node(position)
end
for i, node in ipairs(nodes) do
local idef = minetest.registered_nodes[node.name] local idef = minetest.registered_nodes[node.name]
-- handle the tubes themselves -- handle the tubes themselves
if is_tube(node.name) then if is_tube(node.name) then
active[i] = 1 active[i] = 1
table.insert(adjlist, adj)
-- handle new style connectors -- handle new style connectors
elseif idef and idef.tube and idef.tube.connect_sides then elseif idef and idef.tube and idef.tube.connect_sides then
local dir = adjustments[i] if idef.tube.connect_sides[nodeside(node, vector.multiply(adj, -1))] then
if idef.tube.connect_sides[nodeside(node, vector.multiply(dir, -1))] then
active[i] = 1 active[i] = 1
table.insert(adjlist, adj)
end end
end end
end end
minetest.get_meta(pos):set_string("adjlist", minetest.serialize(adjlist))
-- all sides checked, now figure which tube to use. -- all sides checked, now figure which tube to use.
local nodedef = minetest.registered_nodes[nctr.name] local nodedef = minetest.registered_nodes[nctr.name]

@ -25,7 +25,7 @@ end
-- both optional w/ sensible defaults and fallback to normal allow_* function -- both optional w/ sensible defaults and fallback to normal allow_* function
-- XXX: possibly change insert_object to insert_item -- XXX: possibly change insert_object to insert_item
local adjlist={{x=0,y=0,z=1},{x=0,y=0,z=-1},{x=0,y=1,z=0},{x=0,y=-1,z=0},{x=1,y=0,z=0},{x=-1,y=0,z=0}} local default_adjlist={{x=0,y=0,z=1},{x=0,y=0,z=-1},{x=0,y=1,z=0},{x=0,y=-1,z=0},{x=1,y=0,z=0},{x=-1,y=0,z=0}}
function pipeworks.notvel(tbl, vel) function pipeworks.notvel(tbl, vel)
local tbl2={} local tbl2={}
@ -80,6 +80,9 @@ local function go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner)
if minetest.registered_nodes[cnode.name] and minetest.registered_nodes[cnode.name].tube and minetest.registered_nodes[cnode.name].tube.can_go then if minetest.registered_nodes[cnode.name] and minetest.registered_nodes[cnode.name].tube and minetest.registered_nodes[cnode.name].tube.can_go then
can_go = minetest.registered_nodes[cnode.name].tube.can_go(pos, cnode, vel, stack) can_go = minetest.registered_nodes[cnode.name].tube.can_go(pos, cnode, vel, stack)
else else
local adjlist_string = minetest.get_meta(pos):get_string("adjlist")
local adjlist = minetest.deserialize(adjlist_string) or default_adjlist -- backward compat: if not found, use old behavior: all directions
can_go = pipeworks.notvel(adjlist, vel) can_go = pipeworks.notvel(adjlist, vel)
end end
-- can_go() is expected to return an array-like table of candidate offsets. -- can_go() is expected to return an array-like table of candidate offsets.