Index: lib/node.lua ================================================================== --- lib/node.lua +++ lib/node.lua @@ -1,12 +1,12 @@ local log = sorcery.logger('lib.node') local ofs = { neighbors = { + {x = 0, y = 1, z = 0}; + {x = 0, y = -1, z = 0}; {x = 1, y = 0, z = 0}; {x = -1, y = 0, z = 0}; - {x = 0, y = 1, z = 0}; - {x = 0, y = -1, z = 0}; {x = 0, y = 0, z = 1}; {x = 0, y = 0, z = -1}; }; planecorners = { {x = 1, y = 0, z = 1}; @@ -190,106 +190,156 @@ -- but pepole use these things to build with and that is just way way too many -- meta keys for me to consider it an option. -- -- verdict: not very good, but decent enough for most cases. mtg should have -- done better than this, but now we're all stuck with their bullshit + -- + -- UPDATE: in pratice this is way too expensive to be functional, and causes servers to hang. we're replacing it with a simpler version local treetype = force(pos).name if minetest.get_item_group(treetype, 'tree') == 0 then -- sir this is not a tree return nil -- 無 end local treedef = sorcery.lib.tbl.select(sorcery.data.trees, 'node', treetype) local leaftype = treedef and treedef.leaves or nil + if not leaftype then return false end + local uppermost, lowermost + local found_leaves = false local treemap, treenodes = amass(pos,function(node, where) - if node.name == treetype then - -- abuse predicate function to also track y minimum, so we can - -- avoid iterating over it all later again -- this function is - -- expensive enough already - if (not lowermost) or where.y < lowermost then - lowermost = where.y + print(where, 'treetype',treetype,'node',node.name,node.param1,node.param2) + if node.name == treetype and node.param1 == 0 then + -- abuse predicate so we can avoid iterating over it all later + -- again -- this function is expensive enough already + if (not lowermost) or where.y < lowermost.y then + lowermost = where end - if (not uppermost) or where.y > uppermost then - uppermost = where.y + + if (not uppermost) or where.y > uppermost.y then + uppermost = where end - local m=minetest.get_meta(where) - if m:get_int('sorcery:trunk_node_role') ~= 1 then - return true - else - log.warn('found a log node!') - return false - end - end - if leaftype == nil then - if minetest.get_item_group(node.name, 'leaves') ~= 0 and node.param2 == 0 then - 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') - leaftype = node.name - return true - end - elseif leaftype == node.name and node.param2 == 0 then return true + elseif not found_leaves and node.name == leaftype and node.param2 == 0 then + found_leaves = true end return false - end,ofs.adjoining) - - if leaftype == nil then return false end - - local trunkmap, trunknodes = amass(pos, {treetype}, ofs.adjoining) - if treenodes[leaftype] == nil then return false end - - local cache = {} - local uppermost_check_leaves = true - local topnode - for _, p in pairs(treenodes[treetype]) do - -- if not sorcery.lib.tbl.select(trunknodes[treetype], function(v) - -- return vector.equals(p, v) - -- end, cache) then - -- log.act('tree node', p, 'not accounted for in trunk!') - -- return false - -- end - if p.y == uppermost and uppermost_check_leaves then - topnode = p - uppermost_check_leaves = false - end - if p.y == lowermost then - -- this is the bottom of the tree, bail if it's in not full contact - -- with soil or other eligible nodes as determined by the tree def's - -- 'rooted' predicate - local beneath = vector.offset(p, 0,-1,0); - if treedef.rooted then - if not treedef.rooted { - trunk = p; - groundpos = beneath; - ground = force(beneath); - treemap = treemap; - treenodes = treenodes; - } then return false end - else - if minetest.get_item_group(force(beneath).name, 'soil') == 0 then - return false - end - end + end, ofs.adjoining) + + if not found_leaves then return false end + + -- do -- leaf search + -- local pss, ct = minetest.find_nodes_in_area(uppermost:offset(-1,0,-1), uppermost:offset(1,1,1), leaftype) + -- if ct[leaftype] >= 1 then + -- for _, p in pairs(pss) do + -- local ln = force(p) + -- if ln.param2 == 0 then goto found_leaves end + -- end + -- end + -- return false + -- end + + ::found_leaves:: do -- soil check + local beneath = force(lowermost:offset(0,-1,0)) + if minetest.get_item_group(beneath.name, 'soil') == 0 then + return false end end - if uppermost_check_leaves then - for _,p in pairs(treenodes[leaftype]) do - if p.y == uppermost then - topnode = p - break - end - end - end - -- - --make sure the tree gets enough light - if checklight and minetest.get_natural_light(vector.offset(topnode,0,1,0), 0.5) < 13 then return false end - - -- other possible checks: make sure all ground-touching nodes are directly - -- adjacent + return true, {map = treemap, nodes = treenodes, trunk = treetype, leaves = leaftype, topnode = uppermost, roots = lowermost} + + -- if checklight then iterate to leaf top and check light - return true, {map = treemap, nodes = treenodes, trunk = treetype, leaves = leaftype, topnode = topnode} + -- local uppermost, lowermost + -- + -- local treemap, treenodes = amass(pos,function(node, where) + -- if node.name == treetype then + -- -- abuse predicate function to also track y minimum, so we can + -- -- avoid iterating over it all later again -- this function is + -- -- expensive enough already + -- if (not lowermost) or where.y < lowermost then + -- lowermost = where.y + -- end + -- if (not uppermost) or where.y > uppermost then + -- uppermost = where.y + -- end + -- local m=minetest.get_meta(where) + -- if m:get_int('sorcery:trunk_node_role') ~= 1 then + -- return true + -- else + -- log.warn('found a log node!') + -- return false + -- end + -- end + -- if leaftype == nil then + -- if minetest.get_item_group(node.name, 'leaves') ~= 0 and node.param2 == 0 then + -- 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') + -- leaftype = node.name + -- return true + -- end + -- elseif leaftype == node.name and node.param2 == 0 then + -- return true + -- end + -- return false + -- end,ofs.adjoining) + -- + -- if leaftype == nil then return false end + -- + -- local trunkmap, trunknodes = amass(pos, {treetype}, ofs.adjoining) + -- if treenodes[leaftype] == nil then return false end + -- + -- local cache = {} + -- local uppermost_check_leaves = true + -- local topnode + -- for _, p in pairs(treenodes[treetype]) do + -- -- if not sorcery.lib.tbl.select(trunknodes[treetype], function(v) + -- -- return vector.equals(p, v) + -- -- end, cache) then + -- -- log.act('tree node', p, 'not accounted for in trunk!') + -- -- return false + -- -- end + -- if p.y == uppermost and uppermost_check_leaves then + -- topnode = p + -- uppermost_check_leaves = false + -- end + -- if p.y == lowermost then + -- -- this is the bottom of the tree, bail if it's in not full contact + -- -- with soil or other eligible nodes as determined by the tree def's + -- -- 'rooted' predicate + -- local beneath = vector.offset(p, 0,-1,0); + -- if treedef.rooted then + -- if not treedef.rooted { + -- trunk = p; + -- groundpos = beneath; + -- ground = force(beneath); + -- treemap = treemap; + -- treenodes = treenodes; + -- } then return false end + -- else + -- if minetest.get_item_group(force(beneath).name, 'soil') == 0 then + -- return false + -- end + -- end + -- end + -- end + -- + -- if uppermost_check_leaves then + -- for _,p in pairs(treenodes[leaftype]) do + -- if p.y == uppermost then + -- topnode = p + -- break + -- end + -- end + -- end + -- -- + -- --make sure the tree gets enough light + -- if checklight and minetest.get_natural_light(vector.offset(topnode,0,1,0), 0.5) < 13 then return false end + -- + -- -- other possible checks: make sure all ground-touching nodes are directly + -- -- adjacent + -- + -- return true, {map = treemap, nodes = treenodes, trunk = treetype, leaves = leaftype, topnode = topnode} end; get_arrival_point = function(pos) local try = function(p) local air = sorcery.lib.node.is_clear Index: tap.lua ================================================================== --- tap.lua +++ tap.lua @@ -91,23 +91,23 @@ return end ::found:: local tposhash = minetest.hash_node_position(tpos) local live, should_cache - local mass_leaves, mass_trunk, topnode, prevalidate + local mass_trunk, topnode, prevalidate if abm_cache.treehash[tposhash] then live = true local c = abm_cache.treehash[tposhash] - mass_leaves = c.mass_leaves + -- mass_leaves = c.mass_leaves mass_trunk = c.mass_trunk prevalidate = true else local tbody live, tbody = sorcery.lib.node.tree_is_live(tpos) if live then should_cache = tbody.nodes[tbody.trunk] - mass_leaves = #(tbody.nodes[tbody.leaves]) + -- mass_leaves = #(tbody.nodes[tbody.leaves]) mass_trunk = #(tbody.nodes[tbody.trunk]) * 12 topnode = tbody.topnode end end @@ -116,24 +116,26 @@ or not tree.sapliq then return end if mass_trunk < 12*3 then return end -- too small tapdrip(tree.sapliq,pos) - local mass = mass_leaves + mass_trunk - local max_mass = 400 - local ltratio = mass_leaves / mass_trunk - local mratio = mass / max_mass - local outof = 15 / mratio - local chance = math.max(1, math.floor(outof - (25 * ltratio))) / 3 - local diceroll = math.random(1,chance) + local mass = mass_trunk -- + mass_leaves + local max_mass = 250 -- 400 + -- local ltratio = mass_leaves / mass_trunk + -- local mratio = mass / max_mass + -- local outof = 15 / mratio + -- local chance = math.max(1, math.floor(outof - (25 * ltratio))) / 3 + local chance = mass / max_mass + local diceroll = math.random(1,math.ceil(chance)) -- log.act('rolling dice: ', chance,diceroll, '(lt ratio =', ltratio, '; mass ratio = ', mratio, '; tree mass =', mass, '; outof =', outof) if diceroll ~= 1 then return end -- failed roll - if not prevalidate then - if minetest.get_natural_light(vector.offset(topnode,0,1,0), 0.5) < 13 - then return false end - end + -- if not prevalidate then + -- if minetest.get_natural_light(vector.offset(topnode,0,1,0), 0.5) < 13 + -- then return false end + -- end + -- FIXME for i=1,8 do local at = vector.offset(pos, 0,-i,0) if sorcery.lib.node.is_air(at) then goto skip end @@ -160,12 +162,12 @@ end minetest.swap_node(at, node) end if should_cache then for _,v in pairs(should_cache) do - abm_cache.treehash[v:to_string()] = { - mass_leaves = mass_leaves; + abm_cache.treehash[minetest.hash_node_position(v)] = { + -- mass_leaves = mass_leaves; mass_trunk = mass_trunk; } end end end Index: tree.lua ================================================================== --- tree.lua +++ tree.lua @@ -18,18 +18,20 @@ local def = minetest.registered_nodes[t.node] local nextfn = def.on_place minetest.override_item(t.node, { on_place = function(stack, who, pointed, ...) if nextfn then nextfn(stack, who, pointed, ...) end if who ~= nil and pointed.type == 'node' then - local pos = pointed.above - local _, counts = minetest.find_nodes_in_area( - vector.offset(pos, -1,-1,-1), - vector.offset(pos, 1, 1, 1), - t.leaves or 'group:leaves', false) - if counts[next(counts)] > 0 then - minetest.get_meta(pos):set_int('sorcery:trunk_node_role', 1) - end + -- local pos = pointed.above + -- local _, counts = minetest.find_nodes_in_area( + -- vector.offset(pos, -1,-1,-1), + -- vector.offset(pos, 1, 1, 1), + -- t.leaves or 'group:leaves', false) + -- if counts[next(counts)] > 0 then + local n = minetest.get_node(pointed.above) + n.param1 = 1 + minetest.swap_node(pointed.above, n) + -- end end end }) end if t.sap == false then return end