sorcery  Diff

Differences From Artifact [3dbeb921b1]:

To Artifact [483baaca72]:


     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