sorcery  Check-in [5322b9e068]

Overview
Comment:replace hellaciously overcomplicated function with simpler, faster one
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 5322b9e068dad4419fbb638dffd89260c1ec74b730f7e37c793db5240ba536a3
User & Date: lexi on 2021-07-06 04:18:54
Other Links: manifest | tags
Context
2021-07-06
04:32
fix sap interval check-in: ecfe4b244e user: lexi tags: trunk
04:18
replace hellaciously overcomplicated function with simpler, faster one check-in: 5322b9e068 user: lexi tags: trunk
2021-07-05
23:59
add more recipes and god gifts check-in: 049207a61e user: lexi tags: trunk
Changes

Modified lib/node.lua from [3dbeb921b1] to [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

Modified tap.lua from [43b3147bb9] to [87f184e80e].

    89     89   			end
    90     90   		end do
    91     91   			return
    92     92   		end ::found::
    93     93   
    94     94   		local tposhash = minetest.hash_node_position(tpos)
    95     95   		local live, should_cache
    96         -		local mass_leaves, mass_trunk, topnode, prevalidate
           96  +		local mass_trunk, topnode, prevalidate
    97     97   		if abm_cache.treehash[tposhash] then
    98     98   			live = true
    99     99   			local c = abm_cache.treehash[tposhash]
   100         -			mass_leaves = c.mass_leaves
          100  +			-- mass_leaves = c.mass_leaves
   101    101   			mass_trunk = c.mass_trunk
   102    102   			prevalidate = true
   103    103   		else
   104    104   			local tbody
   105    105   			live, tbody = sorcery.lib.node.tree_is_live(tpos)
   106    106   			if live then
   107    107   				should_cache = tbody.nodes[tbody.trunk]
   108         -				mass_leaves = #(tbody.nodes[tbody.leaves])
          108  +				-- mass_leaves = #(tbody.nodes[tbody.leaves])
   109    109   				mass_trunk = #(tbody.nodes[tbody.trunk]) * 12
   110    110   				topnode = tbody.topnode
   111    111   			end
   112    112   		end
   113    113   
   114    114   		if (not live)
   115    115   			or tree.sap == false
   116    116   			or not tree.sapliq then return end
   117    117   		if mass_trunk < 12*3 then return end -- too small
   118    118   
   119    119   		tapdrip(tree.sapliq,pos)
   120    120   
   121         -		local mass = mass_leaves + mass_trunk
   122         -		local max_mass = 400
   123         -		local ltratio = mass_leaves / mass_trunk
   124         -		local mratio = mass / max_mass
   125         -		local outof = 15 / mratio
   126         -		local chance = math.max(1, math.floor(outof - (25 * ltratio))) / 3
   127         -		local diceroll = math.random(1,chance)
          121  +		local mass = mass_trunk -- + mass_leaves
          122  +		local max_mass = 250 -- 400
          123  +		-- local ltratio = mass_leaves / mass_trunk
          124  +		-- local mratio = mass / max_mass
          125  +		-- local outof = 15 / mratio
          126  +		-- local chance = math.max(1, math.floor(outof - (25 * ltratio))) / 3
          127  +		local chance = mass / max_mass
          128  +		local diceroll = math.random(1,math.ceil(chance))
   128    129   		-- log.act('rolling dice: ', chance,diceroll, '(lt ratio =', ltratio, '; mass ratio = ', mratio, '; tree mass =', mass, '; outof =', outof)
   129    130   		if diceroll ~= 1 then return end -- failed roll
   130    131   
   131         -		if not prevalidate then
   132         -			if minetest.get_natural_light(vector.offset(topnode,0,1,0), 0.5) < 13
   133         -				then return false end
   134         -		end
          132  +		-- if not prevalidate then
          133  +		-- 	if minetest.get_natural_light(vector.offset(topnode,0,1,0), 0.5) < 13
          134  +		-- 		then return false end
          135  +		-- end
          136  +		-- FIXME
   135    137   
   136    138   		for i=1,8 do
   137    139   			local at = vector.offset(pos, 0,-i,0)
   138    140   			if sorcery.lib.node.is_air(at) then goto skip end
   139    141   
   140    142   			local trough = minetest.get_node(at)
   141    143   			if minetest.get_item_group(trough.name, 'sorcery_trough') ~= 0 then
................................................................................
   158    160   							else
   159    161   								node.name = nct.make((ctr.charge or 0) + nct.res,1):get_name()
   160    162   							end
   161    163   							minetest.swap_node(at, node)
   162    164   						end
   163    165   						if should_cache then
   164    166   							for _,v in pairs(should_cache) do
   165         -								abm_cache.treehash[v:to_string()] = {
   166         -									mass_leaves = mass_leaves;
          167  +								abm_cache.treehash[minetest.hash_node_position(v)] = {
          168  +									-- mass_leaves = mass_leaves;
   167    169   									mass_trunk = mass_trunk;
   168    170   								}
   169    171   							end
   170    172   						end
   171    173   					end
   172    174   				else
   173    175   					log.err('item',trough.name,'is marked as a trough but lacks a _sorcery.container property table')
   174    176   				end
   175    177   			end
   176    178   			do return end
   177    179   		::skip::end
   178    180   	end;
   179    181   }

Modified tree.lua from [95c6839cbe] to [e171bc2182].

    16     16   	-- generates sap and hooks handlers appropriately
    17     17   	if t.node then
    18     18   		local def = minetest.registered_nodes[t.node]
    19     19   		local nextfn = def.on_place
    20     20   		minetest.override_item(t.node, { on_place = function(stack, who, pointed, ...)
    21     21   			if nextfn then nextfn(stack, who, pointed, ...) end
    22     22   			if who ~= nil and pointed.type == 'node' then
    23         -				local pos = pointed.above
    24         -				local _, counts = minetest.find_nodes_in_area(
    25         -					vector.offset(pos, -1,-1,-1),
    26         -					vector.offset(pos,  1, 1, 1),
    27         -					t.leaves or 'group:leaves', false)
    28         -				if counts[next(counts)] > 0 then
    29         -					minetest.get_meta(pos):set_int('sorcery:trunk_node_role', 1)
    30         -				end
           23  +				-- local pos = pointed.above
           24  +				-- local _, counts = minetest.find_nodes_in_area(
           25  +				-- 	vector.offset(pos, -1,-1,-1),
           26  +				-- 	vector.offset(pos,  1, 1, 1),
           27  +				-- 	t.leaves or 'group:leaves', false)
           28  +				-- if counts[next(counts)] > 0 then
           29  +				local n = minetest.get_node(pointed.above)
           30  +				n.param1 = 1
           31  +				minetest.swap_node(pointed.above, n)
           32  +				-- end
    31     33   			end
    32     34   		end })
    33     35   	end
    34     36   
    35     37   	if t.sap == false then return end
    36     38   	if not t.sapliq then
    37     39   		t.sapliq = string.format('sorcery:sap_%s', id)