summaryrefslogtreecommitdiff
path: root/mods/vzxv_trees/init.lua
blob: 336465e1d733937fd914fdec60909fafc3686cf2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

vzxv.mundane_block("vzxv_trees:seed","Dirt","moistdirt")
vzxv.mundane_block("vzxv_trees:root","Tree root",{"vzxvmoistdirt.png^vzxvroot.png"})
vzxv.mundane_block("vzxv_trees:core","Tree root",{"vzxvmoistdirt.png^vzxvroot.png"})
vzxv.mundane_block("vzxv_trees:trunk","Tree trunk", {
	"vzxvlog.png","vzxvlog.png","vzxvbark.png"
})

local function traverse(pos, callback)
	local traversed = {}
	local depth = 0
	local function t(pos)
		depth = depth + 1
		if depth > 500 then return end

		local strpos = ('%s,%s,%s'):format(pos.x,pos.y,pos.z)
		if traversed[strpos] then
			return
		else
			traversed[strpos] = true
		end

		local node = minetest.get_node(pos)
		if callback(pos, node) then
			t{pos.x + 1, pos.y    , pos.z    }
			t{pos.x - 1, pos.y    , pos.z    }
			t{pos.x    , pos.y + 1, pos.z    }
			t{pos.x    , pos.y - 1, pos.z    }
			t{pos.x    , pos.y    , pos.z + 1}
			t{pos.x    , pos.y    , pos.z - 1}
		end
	end
	return t(pos)
end

local function update_tree(core_pos)
	local core_meta = minetest.get_meta(core_pos)
	local core = core_meta:to_table()
	if not core or not core.live then
		print "warning: attempt to update nonexistent tree"
		return
	end

	local height = 0
	while 1 do
		local pos = {core_pos.x,core_pos.y+height+1,core_pos.z} 
		local node = minetest.get_node(pos)
		if node.name == "vzxv_trees:trunk" 
				and minetest.get_meta(pos):contains "live" then
			height = height + 1
		else break end
	end

	if height == 0 then
		-- die
		minetest.set_node(core_pos,{name="vzxv_tree:root"})
		return
	end

	local root_budget = 0
	if core.prev_mass then
		if math.log(core.prev_mass * 10) < (core.prev_mass / 5) + height * 2 then
			root_budget = 5
		elseif math.random(50) then
		end
	end

	local root_mass = 0
	traverse(pos, function(pos, node)
		if node.name == "vzxv:root"
				and minetest.get_meta(pos):contains "live" then
			root_mass = root_mass + 1
			return true
		end
	end)
	core.prev = root_mass

	local energy_generated = math.log(root_mass * 10)
	local energy_cost = (root_mass / 5) + height * 2
	core.energy = core.energy + energy_generated - energy_cost

	core_meta:from_table(core)
end

function vzxv.generate_tree(pos)
	local core_pos = {x=pos.x,y=pos.y-1,z=pos.z}
	minetest.set_node(core_pos,{name="vzxv_trees:core"})
	local core = minetest.get_meta(core_pos)

	local height = math.random(8,20)
	for i=0, height do
		local p = {x=pos.x,y=pos.y+i,z=pos.z}
		local node = minetest.get_node(p)
		if node.name ~= "air" and node.name ~= "ignore" then return end
		minetest.set_node({x=pos.x,y=pos.y+i,z=pos.z},{name="vzxv_trees:trunk"})
		minetest.get_meta(p):set_int("live", 1)
	end

	core:from_table {energy=height*10,live=1}
end