Use FIFO queue for mvps (#599)

This commit is contained in:
Jude Melton-Houghton 2022-04-01 17:33:41 -04:00 committed by GitHub
parent 21ac966ee2
commit f4070d3e64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 37 deletions

@ -46,7 +46,8 @@
-- mesecon.rotate_rules_down(rules) -- mesecon.rotate_rules_down(rules)
-- These functions return rules that have been rotated in the specific direction -- These functions return rules that have been rotated in the specific direction
local fifo_queue = dofile(minetest.get_modpath("mesecons").."/fifo_queue.lua") -- See fifo_queue.lua for documentation.
mesecon.fifo_queue = dofile(minetest.get_modpath("mesecons").."/fifo_queue.lua")
-- General -- General
function mesecon.get_effector(nodename) function mesecon.get_effector(nodename)
@ -421,7 +422,7 @@ end
function mesecon.turnon(pos, link) function mesecon.turnon(pos, link)
find_light_update_conductors() find_light_update_conductors()
local frontiers = fifo_queue.new() local frontiers = mesecon.fifo_queue.new()
frontiers:add({pos = pos, link = link}) frontiers:add({pos = pos, link = link})
local pos_can_be_skipped = {} local pos_can_be_skipped = {}
@ -484,7 +485,7 @@ end
function mesecon.turnoff(pos, link) function mesecon.turnoff(pos, link)
find_light_update_conductors() find_light_update_conductors()
local frontiers = fifo_queue.new() local frontiers = mesecon.fifo_queue.new()
frontiers:add({pos = pos, link = link}) frontiers:add({pos = pos, link = link})
local signals = {} local signals = {}
local pos_can_be_skipped = {} local pos_can_be_skipped = {}

@ -63,28 +63,31 @@ end
function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky) function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
-- determine the number of nodes to be pushed -- determine the number of nodes to be pushed
local nodes = {} local nodes = {}
local frontiers = {pos} local pos_set = {}
local frontiers = mesecon.fifo_queue.new()
frontiers:add(vector.new(pos))
while #frontiers > 0 do for np in frontiers:iter() do
local np = frontiers[1] local np_hash = minetest.hash_node_position(np)
local nn = minetest.get_node(np) local nn = not pos_set[np_hash] and minetest.get_node(np)
if nn and not node_replaceable(nn.name) then
if not node_replaceable(nn.name) then pos_set[np_hash] = true
table.insert(nodes, {node = nn, pos = np}) table.insert(nodes, {node = nn, pos = np})
if #nodes > maximum then return nil end if #nodes > maximum then return nil end
-- add connected nodes to frontiers, connected is a vector list -- add connected nodes to frontiers
-- the vectors must be absolute positions
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) local connected = minetest.registered_nodes[nn.name].mvps_sticky(np, nn)
for _, cp in ipairs(connected) do
frontiers:add(cp)
end
end end
table.insert(connected, vector.add(np, dir)) frontiers:add(vector.add(np, dir))
-- If adjacent node is sticky block and connects add that -- If adjacent node is sticky block and connects add that
-- position to the connected table -- position
for _, r in ipairs(mesecon.rules.alldirs) do for _, r in ipairs(mesecon.rules.alldirs) do
local adjpos = vector.add(np, r) local adjpos = vector.add(np, r)
local adjnode = minetest.get_node(adjpos) local adjnode = minetest.get_node(adjpos)
@ -96,36 +99,16 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
-- connects to this position? -- connects to this position?
for _, link in ipairs(sticksto) do for _, link in ipairs(sticksto) do
if vector.equals(link, np) then if vector.equals(link, np) then
table.insert(connected, adjpos) frontiers:add(adjpos)
end end
end end
end end
end end
if all_pull_sticky then if all_pull_sticky then
table.insert(connected, vector.subtract(np, dir)) frontiers:add(vector.subtract(np, dir))
end
-- Make sure there are no duplicates in frontiers / nodes before
-- adding nodes in "connected" to frontiers
for _, cp in ipairs(connected) do
local duplicate = false
for _, rp in ipairs(nodes) do
if vector.equals(cp, rp.pos) then
duplicate = true
end end
end end
for _, fp in ipairs(frontiers) do
if vector.equals(cp, fp) then
duplicate = true
end
end
if not duplicate then
table.insert(frontiers, cp)
end
end
end
table.remove(frontiers, 1)
end end
return nodes return nodes