63
63
function mesecon .mvps_get_stack (pos , dir , maximum , all_pull_sticky )
64
64
-- determine the number of nodes to be pushed
65
65
local nodes = {}
66
- local frontiers = {pos }
67
-
68
- while # frontiers > 0 do
69
- local np = frontiers [1 ]
70
- local nn = minetest .get_node (np )
71
-
72
- if not node_replaceable (nn .name ) then
66
+ local pos_set = {}
67
+ local frontiers = mesecon .fifo_queue .new ()
68
+ frontiers :add (vector .new (pos ))
69
+
70
+ for np in frontiers :iter () do
71
+ local np_hash = minetest .hash_node_position (np )
72
+ local nn = not pos_set [np_hash ] and minetest .get_node (np )
73
+ if nn and not node_replaceable (nn .name ) then
74
+ pos_set [np_hash ] = true
73
75
table.insert (nodes , {node = nn , pos = np })
74
76
if # nodes > maximum then return nil end
75
77
76
- -- add connected nodes to frontiers, connected is a vector list
77
- -- the vectors must be absolute positions
78
- local connected = {}
78
+ -- add connected nodes to frontiers
79
79
if minetest .registered_nodes [nn .name ]
80
80
and minetest .registered_nodes [nn .name ].mvps_sticky then
81
- connected = minetest .registered_nodes [nn .name ].mvps_sticky (np , nn )
81
+ local connected = minetest .registered_nodes [nn .name ].mvps_sticky (np , nn )
82
+ for _ , cp in ipairs (connected ) do
83
+ frontiers :add (cp )
84
+ end
82
85
end
83
86
84
- table.insert ( connected , vector .add (np , dir ))
87
+ frontiers : add ( vector .add (np , dir ))
85
88
86
89
-- If adjacent node is sticky block and connects add that
87
- -- position to the connected table
90
+ -- position
88
91
for _ , r in ipairs (mesecon .rules .alldirs ) do
89
92
local adjpos = vector .add (np , r )
90
93
local adjnode = minetest .get_node (adjpos )
@@ -96,36 +99,16 @@ function mesecon.mvps_get_stack(pos, dir, maximum, all_pull_sticky)
96
99
-- connects to this position?
97
100
for _ , link in ipairs (sticksto ) do
98
101
if vector .equals (link , np ) then
99
- table.insert ( connected , adjpos )
102
+ frontiers : add ( adjpos )
100
103
end
101
104
end
102
105
end
103
106
end
104
107
105
108
if all_pull_sticky then
106
- table.insert (connected , vector .subtract (np , dir ))
107
- end
108
-
109
- -- Make sure there are no duplicates in frontiers / nodes before
110
- -- adding nodes in "connected" to frontiers
111
- for _ , cp in ipairs (connected ) do
112
- local duplicate = false
113
- for _ , rp in ipairs (nodes ) do
114
- if vector .equals (cp , rp .pos ) then
115
- duplicate = true
116
- end
117
- end
118
- for _ , fp in ipairs (frontiers ) do
119
- if vector .equals (cp , fp ) then
120
- duplicate = true
121
- end
122
- end
123
- if not duplicate then
124
- table.insert (frontiers , cp )
125
- end
109
+ frontiers :add (vector .subtract (np , dir ))
126
110
end
127
111
end
128
- table.remove (frontiers , 1 )
129
112
end
130
113
131
114
return nodes
0 commit comments