Differences From
Artifact [3dbeb921b1]:
1 1 local log = sorcery.logger('lib.node')
2 2 local ofs = {
3 3 neighbors = {
4 + {x = 0, y = 1, z = 0};
5 + {x = 0, y = -1, z = 0};
4 6 {x = 1, y = 0, z = 0};
5 7 {x = -1, y = 0, z = 0};
6 - {x = 0, y = 1, z = 0};
7 - {x = 0, y = -1, z = 0};
8 8 {x = 0, y = 0, z = 1};
9 9 {x = 0, y = 0, z = -1};
10 10 };
11 11 planecorners = {
12 12 {x = 1, y = 0, z = 1};
13 13 {x = -1, y = 0, z = 1};
14 14 {x = -1, y = 0, z = -1};
................................................................................
188 188 -- various problems could be avoided by unconditionally inserted the meta key,
189 189 -- or inserting it also when it comes into contact with another trunk node,
190 190 -- but pepole use these things to build with and that is just way way too many
191 191 -- meta keys for me to consider it an option.
192 192 --
193 193 -- verdict: not very good, but decent enough for most cases. mtg should have
194 194 -- done better than this, but now we're all stuck with their bullshit
195 + --
196 + -- UPDATE: in pratice this is way too expensive to be functional, and causes servers to hang. we're replacing it with a simpler version
195 197
196 198 local treetype = force(pos).name
197 199 if minetest.get_item_group(treetype, 'tree') == 0 then -- sir this is not a tree
198 200 return nil -- 無
199 201 end
200 202 local treedef = sorcery.lib.tbl.select(sorcery.data.trees, 'node', treetype)
201 203 local leaftype = treedef and treedef.leaves or nil
204 + if not leaftype then return false end
205 +
202 206 local uppermost, lowermost
207 + local found_leaves = false
203 208
204 209 local treemap, treenodes = amass(pos,function(node, where)
205 - if node.name == treetype then
206 - -- abuse predicate function to also track y minimum, so we can
207 - -- avoid iterating over it all later again -- this function is
208 - -- expensive enough already
209 - if (not lowermost) or where.y < lowermost then
210 - lowermost = where.y
210 + print(where, 'treetype',treetype,'node',node.name,node.param1,node.param2)
211 + if node.name == treetype and node.param1 == 0 then
212 + -- abuse predicate so we can avoid iterating over it all later
213 + -- again -- this function is expensive enough already
214 + if (not lowermost) or where.y < lowermost.y then
215 + lowermost = where
211 216 end
212 - if (not uppermost) or where.y > uppermost then
213 - uppermost = where.y
217 +
218 + if (not uppermost) or where.y > uppermost.y then
219 + uppermost = where
214 220 end
215 - local m=minetest.get_meta(where)
216 - if m:get_int('sorcery:trunk_node_role') ~= 1 then
217 - return true
218 - else
219 - log.warn('found a log node!')
220 - return false
221 - end
222 - end
223 - if leaftype == nil then
224 - if minetest.get_item_group(node.name, 'leaves') ~= 0 and node.param2 == 0 then
225 - log.warn('guessing leaf node for tree',treetype,'is',node.name,'; please report this bug to the mod responsible for this tree and ask for appropriate Sorcery interop code to be added')
226 - leaftype = node.name
227 - return true
228 - end
229 - elseif leaftype == node.name and node.param2 == 0 then
230 221 return true
222 + elseif not found_leaves and node.name == leaftype and node.param2 == 0 then
223 + found_leaves = true
231 224 end
232 225 return false
233 - end,ofs.adjoining)
234 -
235 - if leaftype == nil then return false end
236 -
237 - local trunkmap, trunknodes = amass(pos, {treetype}, ofs.adjoining)
238 - if treenodes[leaftype] == nil then return false end
239 -
240 - local cache = {}
241 - local uppermost_check_leaves = true
242 - local topnode
243 - for _, p in pairs(treenodes[treetype]) do
244 - -- if not sorcery.lib.tbl.select(trunknodes[treetype], function(v)
245 - -- return vector.equals(p, v)
246 - -- end, cache) then
247 - -- log.act('tree node', p, 'not accounted for in trunk!')
248 - -- return false
249 - -- end
250 - if p.y == uppermost and uppermost_check_leaves then
251 - topnode = p
252 - uppermost_check_leaves = false
253 - end
254 - if p.y == lowermost then
255 - -- this is the bottom of the tree, bail if it's in not full contact
256 - -- with soil or other eligible nodes as determined by the tree def's
257 - -- 'rooted' predicate
258 - local beneath = vector.offset(p, 0,-1,0);
259 - if treedef.rooted then
260 - if not treedef.rooted {
261 - trunk = p;
262 - groundpos = beneath;
263 - ground = force(beneath);
264 - treemap = treemap;
265 - treenodes = treenodes;
266 - } then return false end
267 - else
268 - if minetest.get_item_group(force(beneath).name, 'soil') == 0 then
269 - return false
270 - end
271 - end
226 + end, ofs.adjoining)
227 +
228 + if not found_leaves then return false end
229 +
230 + -- do -- leaf search
231 + -- local pss, ct = minetest.find_nodes_in_area(uppermost:offset(-1,0,-1), uppermost:offset(1,1,1), leaftype)
232 + -- if ct[leaftype] >= 1 then
233 + -- for _, p in pairs(pss) do
234 + -- local ln = force(p)
235 + -- if ln.param2 == 0 then goto found_leaves end
236 + -- end
237 + -- end
238 + -- return false
239 + -- end
240 +
241 + ::found_leaves:: do -- soil check
242 + local beneath = force(lowermost:offset(0,-1,0))
243 + if minetest.get_item_group(beneath.name, 'soil') == 0 then
244 + return false
272 245 end
273 246 end
274 247
275 - if uppermost_check_leaves then
276 - for _,p in pairs(treenodes[leaftype]) do
277 - if p.y == uppermost then
278 - topnode = p
279 - break
280 - end
281 - end
282 - end
283 - --
284 - --make sure the tree gets enough light
285 - if checklight and minetest.get_natural_light(vector.offset(topnode,0,1,0), 0.5) < 13 then return false end
286 -
287 - -- other possible checks: make sure all ground-touching nodes are directly
288 - -- adjacent
248 + return true, {map = treemap, nodes = treenodes, trunk = treetype, leaves = leaftype, topnode = uppermost, roots = lowermost}
249 +
250 + -- if checklight then iterate to leaf top and check light
289 251
290 - return true, {map = treemap, nodes = treenodes, trunk = treetype, leaves = leaftype, topnode = topnode}
252 + -- local uppermost, lowermost
253 + --
254 + -- local treemap, treenodes = amass(pos,function(node, where)
255 + -- if node.name == treetype then
256 + -- -- abuse predicate function to also track y minimum, so we can
257 + -- -- avoid iterating over it all later again -- this function is
258 + -- -- expensive enough already
259 + -- if (not lowermost) or where.y < lowermost then
260 + -- lowermost = where.y
261 + -- end
262 + -- if (not uppermost) or where.y > uppermost then
263 + -- uppermost = where.y
264 + -- end
265 + -- local m=minetest.get_meta(where)
266 + -- if m:get_int('sorcery:trunk_node_role') ~= 1 then
267 + -- return true
268 + -- else
269 + -- log.warn('found a log node!')
270 + -- return false
271 + -- end
272 + -- end
273 + -- if leaftype == nil then
274 + -- if minetest.get_item_group(node.name, 'leaves') ~= 0 and node.param2 == 0 then
275 + -- log.warn('guessing leaf node for tree',treetype,'is',node.name,'; please report this bug to the mod responsible for this tree and ask for appropriate Sorcery interop code to be added')
276 + -- leaftype = node.name
277 + -- return true
278 + -- end
279 + -- elseif leaftype == node.name and node.param2 == 0 then
280 + -- return true
281 + -- end
282 + -- return false
283 + -- end,ofs.adjoining)
284 + --
285 + -- if leaftype == nil then return false end
286 + --
287 + -- local trunkmap, trunknodes = amass(pos, {treetype}, ofs.adjoining)
288 + -- if treenodes[leaftype] == nil then return false end
289 + --
290 + -- local cache = {}
291 + -- local uppermost_check_leaves = true
292 + -- local topnode
293 + -- for _, p in pairs(treenodes[treetype]) do
294 + -- -- if not sorcery.lib.tbl.select(trunknodes[treetype], function(v)
295 + -- -- return vector.equals(p, v)
296 + -- -- end, cache) then
297 + -- -- log.act('tree node', p, 'not accounted for in trunk!')
298 + -- -- return false
299 + -- -- end
300 + -- if p.y == uppermost and uppermost_check_leaves then
301 + -- topnode = p
302 + -- uppermost_check_leaves = false
303 + -- end
304 + -- if p.y == lowermost then
305 + -- -- this is the bottom of the tree, bail if it's in not full contact
306 + -- -- with soil or other eligible nodes as determined by the tree def's
307 + -- -- 'rooted' predicate
308 + -- local beneath = vector.offset(p, 0,-1,0);
309 + -- if treedef.rooted then
310 + -- if not treedef.rooted {
311 + -- trunk = p;
312 + -- groundpos = beneath;
313 + -- ground = force(beneath);
314 + -- treemap = treemap;
315 + -- treenodes = treenodes;
316 + -- } then return false end
317 + -- else
318 + -- if minetest.get_item_group(force(beneath).name, 'soil') == 0 then
319 + -- return false
320 + -- end
321 + -- end
322 + -- end
323 + -- end
324 + --
325 + -- if uppermost_check_leaves then
326 + -- for _,p in pairs(treenodes[leaftype]) do
327 + -- if p.y == uppermost then
328 + -- topnode = p
329 + -- break
330 + -- end
331 + -- end
332 + -- end
333 + -- --
334 + -- --make sure the tree gets enough light
335 + -- if checklight and minetest.get_natural_light(vector.offset(topnode,0,1,0), 0.5) < 13 then return false end
336 + --
337 + -- -- other possible checks: make sure all ground-touching nodes are directly
338 + -- -- adjacent
339 + --
340 + -- return true, {map = treemap, nodes = treenodes, trunk = treetype, leaves = leaftype, topnode = topnode}
291 341 end;
292 342
293 343 get_arrival_point = function(pos)
294 344 local try = function(p)
295 345 local air = sorcery.lib.node.is_clear
296 346 if air(p) then
297 347 if air(vector.offset(p,0,1,0)) then return p end