From f4070d3e64652837e4c79967f29bf67f0ac559f4 Mon Sep 17 00:00:00 2001 From: Jude Melton-Houghton Date: Fri, 1 Apr 2022 17:33:41 -0400 Subject: [PATCH] Use FIFO queue for mvps (#599) --- mesecons/internal.lua | 7 +++--- mesecons_mvps/init.lua | 51 ++++++++++++++---------------------------- 2 files changed, 21 insertions(+), 37 deletions(-) diff --git a/mesecons/internal.lua b/mesecons/internal.lua index e6d20e4..6f52b44 100644 --- a/mesecons/internal.lua +++ b/mesecons/internal.lua @@ -46,7 +46,8 @@ -- mesecon.rotate_rules_down(rules) -- 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 function mesecon.get_effector(nodename) @@ -421,7 +422,7 @@ end function mesecon.turnon(pos, link) find_light_update_conductors() - local frontiers = fifo_queue.new() + local frontiers = mesecon.fifo_queue.new() frontiers:add({pos = pos, link = link}) local pos_can_be_skipped = {} @@ -484,7 +485,7 @@ end function mesecon.turnoff(pos, link) find_light_update_conductors() - local frontiers = fifo_queue.new() + local frontiers = mesecon.fifo_queue.new() frontiers:add({pos = pos, link = link}) local signals = {} local pos_can_be_skipped = {} diff --git a/mesecons_mvps/init.lua b/mesecons_mvps/init.lua index e3038a6..31f103c 100644 --- a/mesecons_mvps/init.lua +++ b/mesecons_mvps/init.lua @@ -63,28 +63,31 @@ end function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky) -- determine the number of nodes to be pushed local nodes = {} - local frontiers = {pos} + local pos_set = {} + local frontiers = mesecon.fifo_queue.new() + frontiers:add(vector.new(pos)) - while #frontiers > 0 do - local np = frontiers[1] - local nn = minetest.get_node(np) - - if not node_replaceable(nn.name) then + for np in frontiers:iter() do + local np_hash = minetest.hash_node_position(np) + local nn = not pos_set[np_hash] and minetest.get_node(np) + if nn and not node_replaceable(nn.name) then + pos_set[np_hash] = true table.insert(nodes, {node = nn, pos = np}) if #nodes > maximum then return nil end - -- add connected nodes to frontiers, connected is a vector list - -- the vectors must be absolute positions - local connected = {} + -- add connected nodes to frontiers 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) + local connected = minetest.registered_nodes[nn.name].mvps_sticky(np, nn) + for _, cp in ipairs(connected) do + frontiers:add(cp) + 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 - -- position to the connected table + -- position for _, r in ipairs(mesecon.rules.alldirs) do local adjpos = vector.add(np, r) 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? for _, link in ipairs(sticksto) do if vector.equals(link, np) then - table.insert(connected, adjpos) + frontiers:add(adjpos) end end end end if all_pull_sticky then - table.insert(connected, 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 - 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 + frontiers:add(vector.subtract(np, dir)) end end - table.remove(frontiers, 1) end return nodes