Compare commits
26 Commits
9c28941a6a
...
3fa17f8b68
Author | SHA1 | Date |
---|---|---|
trans_soup | 3fa17f8b68 | |
trans_soup | 845e951d8d | |
trans_soup | ecd04f8105 | |
trans_soup | 37d192798e | |
trans_soup | 123d3329cd | |
trans_soup | e42407978d | |
trans_soup | 400c27c021 | |
trans_soup | ae26cfad42 | |
trans_soup | a3537b5dda | |
trans_soup | 292358a3db | |
trans_soup | 737afdfcc9 | |
trans_soup | 7493d9771c | |
trans_soup | 87a88a88a6 | |
trans_soup | 717cbf91e2 | |
trans_soup | 584187957a | |
trans_soup | c3bff227aa | |
trans_soup | 3316dcba15 | |
trans_soup | 477afad09e | |
trans_soup | 1282fda837 | |
trans_soup | 0dffde9363 | |
trans_soup | f134082112 | |
trans_soup | bdfb9f5fda | |
trans_soup | 19e392d1f3 | |
trans_soup | 68e005814f | |
trans_soup | dd796c549e | |
trans_soup | 9e43abb69a |
|
@ -24,4 +24,6 @@ load_file("increasing_abm")
|
|||
load_file("loose_node")
|
||||
load_file("fall_fix")
|
||||
|
||||
load_file("privs")
|
||||
|
||||
load_file("cleanup")
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
|
||||
minetest.register_privilege("control_time", "control the speed at which certain blockgame processes happen.")
|
|
@ -8,10 +8,18 @@ end
|
|||
|
||||
|
||||
|
||||
function blockgame.attempt_place (pos, node)
|
||||
if minetest.get_node(pos).name ~= "air" then return false end
|
||||
minetest.set_node(pos, node)
|
||||
return true
|
||||
function blockgame.attempt_place (pos, node, replacable)
|
||||
local replacable = replacable or {}
|
||||
local node_name = minetest.get_node(pos).name
|
||||
local can_place = false
|
||||
|
||||
if node_name == "air" then can_place = true end
|
||||
if blockgame.item_matches(node_name, replacable) then can_place = true end
|
||||
|
||||
if can_place then
|
||||
minetest.set_node(pos, node)
|
||||
end
|
||||
return can_place
|
||||
end
|
||||
|
||||
|
||||
|
@ -74,3 +82,38 @@ function blockgame.flood_fill (start, step, max_range)
|
|||
|
||||
return matches, rejected
|
||||
end
|
||||
|
||||
|
||||
|
||||
function blockgame.score_nearby_nodes (pos, max_distance, group_scores, score_fn)
|
||||
local score = 0
|
||||
local source_pos = pos
|
||||
|
||||
blockgame.flood_fill(pos, function (pos, distance)
|
||||
if pos == source_pos then return true end
|
||||
|
||||
local name = minetest.get_node(pos).name
|
||||
|
||||
local gain = 0
|
||||
-- TODO: add support for individual nodes and not just groups.
|
||||
for group, value in pairs(group_scores) do
|
||||
local group = minetest.get_item_group(name, group)
|
||||
if group > 0 then
|
||||
gain = math.max(gain, value * group)
|
||||
end
|
||||
end
|
||||
|
||||
gain = score_fn(gain, distance, name, pos)
|
||||
|
||||
-- TODO: add support for optionally counting negative scores.
|
||||
if gain > 0 then
|
||||
score = score + gain
|
||||
return true
|
||||
end
|
||||
|
||||
-- TODO: add support for optionally going through non-scored nodes.
|
||||
return false
|
||||
end, max_distance)
|
||||
|
||||
return score
|
||||
end
|
||||
|
|
|
@ -1,13 +1,45 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local api = blockgame.tree
|
||||
local vec = blockgame.vector
|
||||
|
||||
-- NODE NAMES
|
||||
|
||||
local leaves = modname .. ":leaves"
|
||||
local leaves_decomposing = modname .. ":leaves_decomposing"
|
||||
|
||||
-- END OF NODE NAMES
|
||||
|
||||
|
||||
local decompose_time_speed = 1
|
||||
-- TODO: add setting for this as well.
|
||||
minetest.register_chatcommand(modname .. ":set_decompose_time_speed", {
|
||||
params = "<value>",
|
||||
description = "set the speed at which decomposition happens.",
|
||||
privs = {
|
||||
control_time = true,
|
||||
},
|
||||
func = function (player_name, speed)
|
||||
speed = tonumber(speed)
|
||||
if speed == nil then
|
||||
minetest.chat_send_player(player_name, "time speed must be a number.")
|
||||
return
|
||||
end
|
||||
if speed < 0 or speed > 256 then
|
||||
minetest.chat_send_player(player_name, "time speed must be between 0 and 256 (inclusive).")
|
||||
return
|
||||
end
|
||||
|
||||
decompose_time_speed = speed
|
||||
minetest.chat_send_all(player_name .. " set the leaves decomposition time speed to " .. speed .. ".")
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
|
||||
local decompose_scores = {
|
||||
dirty = 100,
|
||||
leaves_decomposing = 20,
|
||||
}
|
||||
|
||||
local start_decompose_cost = 4000
|
||||
|
||||
blockgame.register_increasing_abm({
|
||||
id = modname .. ":begin_decompose",
|
||||
|
@ -15,60 +47,44 @@ blockgame.register_increasing_abm({
|
|||
nodenames = {leaves},
|
||||
neighbors = {"group:dirty", leaves_decomposing},
|
||||
interval = 15,
|
||||
chance = 4,
|
||||
chance = 8,
|
||||
rate = function (pos, node, data)
|
||||
return data.value + math.random(4, 6)
|
||||
local score = blockgame.score_nearby_nodes(pos, 2, decompose_scores, function (gain, distance)
|
||||
return math.floor(gain / (distance ^ 3))
|
||||
end)
|
||||
|
||||
return data.value + score * decompose_time_speed
|
||||
end,
|
||||
check = function (pos, node, data)
|
||||
return data.value >= 20
|
||||
return data.value >= start_decompose_cost
|
||||
end,
|
||||
action = function (pos, node, data)
|
||||
minetest.set_node(pos, {name = leaves_decomposing})
|
||||
-- NOTE: might wanna access the 4 from somewhere, instead of directly knowing it.
|
||||
-- that way this won't have to change if decomposing leaves max levels change.
|
||||
local level = math.random(1, 4)
|
||||
minetest.set_node(pos, {name = leaves_decomposing .. "_" .. level})
|
||||
end,
|
||||
})
|
||||
|
||||
local decompose_scores = {
|
||||
dirty = 50,
|
||||
leaves_decomposing = 30,
|
||||
}
|
||||
|
||||
local decompose_cost = 2000
|
||||
local decompose_cost = 30000
|
||||
local average_leaves_per_dirt = 4
|
||||
|
||||
blockgame.register_increasing_abm({
|
||||
id = modname .. ":decompose",
|
||||
label = "decompose leaves",
|
||||
nodenames = {"group:leaves_decomposing"},
|
||||
-- neighbors = {"group:dirty", "group:leaves_decomposing"},
|
||||
interval = 30,
|
||||
neighbors = {"group:dirty"},
|
||||
interval = 15,
|
||||
chance = 10,
|
||||
rate = function (pos, node, data)
|
||||
local score = 100
|
||||
local score = 20
|
||||
|
||||
local source_pos = pos
|
||||
blockgame.flood_fill(pos, function (pos, distance)
|
||||
if pos == source_pos then return true end
|
||||
local bonus = blockgame.score_nearby_nodes(pos, 4, decompose_scores, function (gain, distance)
|
||||
return math.floor(gain / (distance ^ 3))
|
||||
end)
|
||||
|
||||
local name = minetest.get_node(pos).name
|
||||
|
||||
local gain = 0
|
||||
for group, value in pairs(decompose_scores) do
|
||||
local group = minetest.get_item_group(name, group)
|
||||
if group > 0 then
|
||||
gain = math.max(gain, value * group)
|
||||
end
|
||||
end
|
||||
|
||||
gain = math.floor(gain / distance)
|
||||
|
||||
if gain > 0 then
|
||||
score = score + gain
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end, 4)
|
||||
|
||||
return data.value + score
|
||||
score = score + bonus
|
||||
return data.value + score * decompose_time_speed
|
||||
end,
|
||||
check = function (pos, node, data)
|
||||
return data.value >= decompose_cost
|
||||
|
@ -79,10 +95,11 @@ blockgame.register_increasing_abm({
|
|||
local def = minetest.registered_nodes[node.name]
|
||||
local dirt_chance = def.level_max - def.level + 1
|
||||
|
||||
if blockgame.chance(dirt_chance) then
|
||||
if blockgame.chance(dirt_chance * average_leaves_per_dirt) then
|
||||
minetest.set_node(pos, {name = "bg_terrain:dirt"})
|
||||
else
|
||||
minetest.remove_node(pos)
|
||||
minetest.check_for_falling(pos)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
|
|
@ -7,27 +7,40 @@ local leaves = modname .. ":leaves"
|
|||
local leaves_growing = modname .. ":leaves_growing"
|
||||
local leaves_alive = modname .. ":leaves_alive"
|
||||
|
||||
-- END OF NODE NAMES
|
||||
|
||||
|
||||
local max_grow_distance = 2
|
||||
local leaves_grow_cost = 250
|
||||
|
||||
-- TODO: turn this into an increasing ABM.
|
||||
blockgame.register_abm({
|
||||
blockgame.register_increasing_abm({
|
||||
id = modname .. ":grow_leaves",
|
||||
label = "grow leaves",
|
||||
nodenames = {leaves_growing},
|
||||
neighbors = {log_alive, leaves_growing, leaves_alive},
|
||||
interval = 15,
|
||||
chance = 8,
|
||||
action = function (pos, node)
|
||||
rate = function (pos, node, data)
|
||||
-- TODO: account for nearby nodes? e.g. grow slower if there are more leaves nearby.
|
||||
return data.value + math.random(1, 99)
|
||||
end,
|
||||
check = function (pos, node, data)
|
||||
return data.value >= leaves_grow_cost
|
||||
end,
|
||||
action = function (pos, node, data)
|
||||
-- TODO: give leaves energy over time, that they spend when creating new leaves.
|
||||
-- this requires the API to add support for increasing ABM `action`:s to modify `data`.
|
||||
local meta = minetest.get_meta(pos)
|
||||
local distance = meta:get_int("leaf_distance") or 1
|
||||
if distance >= max_grow_distance then return end
|
||||
if distance >= max_grow_distance then
|
||||
minetest.set_node(pos, {name = leaves_alive})
|
||||
return
|
||||
end
|
||||
|
||||
local neighbors = blockgame.vector.get_neighbors(pos)
|
||||
for _, target in pairs(neighbors) do
|
||||
local sides = blockgame.vector.get_sides_of(pos)
|
||||
for _, target in pairs(sides) do
|
||||
if blockgame.chance(2) then
|
||||
blockgame.attempt_place(target, {name = leaves_growing})
|
||||
-- TODO: find lowest possible leaf distance by checking all 4 sides?
|
||||
minetest.get_meta(target):set_int("leaf_distance", distance + 1)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
|
||||
local root_alive = modname .. ":root_alive"
|
||||
|
||||
blockgame.register_abm({
|
||||
label = "kill roots",
|
||||
nodenames = {root_alive},
|
||||
interval = 20,
|
||||
chance = 1,
|
||||
action = function (pos, node)
|
||||
local can_live = blockgame.any(blockgame.vector.get_neighbors(pos), function (pos)
|
||||
return blockgame.item_matches(minetest.get_node(pos).name, {
|
||||
root_alive,
|
||||
modname .. ":log_alive",
|
||||
modname .. ":sapling",
|
||||
})
|
||||
end)
|
||||
|
||||
if can_live then return end
|
||||
|
||||
minetest.set_node(pos, {name = modname .. ":root"})
|
||||
end,
|
||||
})
|
|
@ -9,8 +9,10 @@ local leaves_growing = modname .. ":leaves_growing"
|
|||
|
||||
|
||||
local function supports_sapling (name)
|
||||
if name == log_alive or name == root_alive then return true end
|
||||
return minetest.get_item_group(name, "dirty") > 0
|
||||
return blockgame.item_matches(name, {
|
||||
"group:supports_sapling",
|
||||
"group:dirty",
|
||||
})
|
||||
end
|
||||
|
||||
-- this commented-out function will be used when roots start affecting tree growth.
|
||||
|
@ -35,26 +37,32 @@ local function find_first_root (pos, max_height = 8)
|
|||
end
|
||||
]]--
|
||||
|
||||
local sapling_grow_cost = 2000
|
||||
local sapling_can_replace = {
|
||||
modname .. ":leaves_alive",
|
||||
}
|
||||
|
||||
blockgame.register_increasing_abm({
|
||||
id = modname .. ":grow_sapling",
|
||||
label = "grow sapling",
|
||||
nodenames = {sapling},
|
||||
neighbors = {"group:dirty", log_alive},
|
||||
neighbors = {"group:supports_sapling", "group:dirty"},
|
||||
interval = 15,
|
||||
chance = 4,
|
||||
rate = function (pos, node, data)
|
||||
-- TODO: find connected living logs and leaves, and nearby light levels, and soil richness near roots, to calculate growth rate.
|
||||
return data.value + math.random(1, 99)
|
||||
return data.value + math.random(1, 100) * math.random(1, 5)
|
||||
end,
|
||||
check = function (pos, node, data)
|
||||
if data.value < 200 then return false end
|
||||
if data.value < sapling_grow_cost then return false end
|
||||
|
||||
local below = pos + blockgame.vector.dirs.down
|
||||
local below_name = minetest.get_node(below).name
|
||||
if not supports_sapling(below_name) then return false end
|
||||
|
||||
local above = pos + blockgame.vector.dirs.up
|
||||
if minetest.get_node(above).name ~= "air" then return false end
|
||||
local above_name = minetest.get_node(above).name
|
||||
if above_name ~= "air" and not blockgame.item_matches(above_name, sapling_can_replace) then return false end
|
||||
|
||||
return true
|
||||
end,
|
||||
|
@ -81,7 +89,7 @@ blockgame.register_increasing_abm({
|
|||
end
|
||||
|
||||
-- grow out leaves to the sides.
|
||||
local sides = blockgame.vector.get_sides_of(pos)
|
||||
local sides = blockgame.vector.get_sides_of(above)
|
||||
for _, side in pairs(sides) do
|
||||
blockgame.attempt_place(side, {name = leaves_growing})
|
||||
end
|
||||
|
|
|
@ -5,6 +5,7 @@ load_file("decoration")
|
|||
|
||||
load_file("grow_sapling")
|
||||
load_file("grow_leaves")
|
||||
load_file("grow_root")
|
||||
|
||||
load_file("fall_leaves")
|
||||
load_file("decompose")
|
||||
|
|
|
@ -19,5 +19,7 @@ blockgame.register_node("root_alive", {
|
|||
description = "Growing Root",
|
||||
groups = {
|
||||
woody = 1,
|
||||
supports_sapling = 1,
|
||||
},
|
||||
drop = modname .. ":root",
|
||||
})
|
||||
|
|
|
@ -28,12 +28,12 @@ local nutty_drops = {
|
|||
max_items = 3,
|
||||
items = {
|
||||
{
|
||||
rarity = 8,
|
||||
items = {modname .. ":nut"},
|
||||
rarity = 20,
|
||||
items = {modname .. ":nut 2"},
|
||||
},
|
||||
{
|
||||
rarity = 12,
|
||||
items = {modname .. ":nut 2"},
|
||||
rarity = 16,
|
||||
items = {modname .. ":nut"},
|
||||
},
|
||||
{
|
||||
rarity = 1,
|
||||
|
@ -112,6 +112,7 @@ local function reg_decomposing (level)
|
|||
texture = "leaves_decomposing",
|
||||
drawtype = drawtype,
|
||||
node_box = node_box,
|
||||
on_construct = after_place_stack,
|
||||
after_place_node = after_place_stack,
|
||||
after_land = after_place_stack,
|
||||
drop = modname .. ":leaves_decomposing_1 " .. level,
|
||||
|
|
|
@ -28,6 +28,7 @@ reg_log("log", {
|
|||
reg_log("log_alive", {
|
||||
groups = {
|
||||
planty = 1,
|
||||
supports_sapling = 1,
|
||||
},
|
||||
texture = "log",
|
||||
drop = modname .. ":log",
|
||||
|
|
Loading…
Reference in New Issue