166cfe5f14
The problem was pointed out by Josh (gitlab.com/krazy-j) in merge request !22. Apparently MT is not very smart about marking mapblocks dirty to send to clients based on calling mt.set_node(), i.e. it will mark them dirty presumptively even if you set the node to the same value it had already been. This behavior can be confirmed by registering an ABM against a common node like grass and setting action = minetest.set_node. This causes every mapblock containing that node to be invalidated every interval, causing a big spike in the packets received each interval that you can clearly see on the F5 graph. Rather than just fixing it for the most easily observed case (fire checks), add utlity functions to check this for ALL node change situations, and apply it more or less universally anywhere that we are not certain that the node is being changed and we don't need to worry about the extra overhead cost of the check. Note that we don't need a nodecore.set_loud_check call, as set_loud was only ever being used already in cases where we were pretty sure we were actually changing a node.
226 lines
6.6 KiB
Lua
226 lines
6.6 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local math, minetest, nodecore, pairs, table
|
|
= math, minetest, nodecore, pairs, table
|
|
local math_random, table_concat
|
|
= math.random, table.concat
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local modname = minetest.get_current_modname()
|
|
|
|
local function growparticles(pos, rate, width)
|
|
nodecore.soaking_particles(pos, rate, 10, width, modname .. ":leaves_bud")
|
|
end
|
|
|
|
local sproutcost = 2000
|
|
nodecore.register_soaking_abm({
|
|
label = "eggcorn sprout",
|
|
fieldname = "eggcorn",
|
|
nodenames = {modname .. ":eggcorn_planted"},
|
|
interval = 10,
|
|
arealoaded = 1,
|
|
soakrate = nodecore.tree_growth_rate,
|
|
soakcheck = function(data, pos)
|
|
if data.total >= sproutcost then
|
|
nodecore.node_sound(pos, "dig")
|
|
nodecore.set_loud(pos, {name = modname .. ":root"})
|
|
local apos = {x = pos.x, y = pos.y + 1, z = pos.z}
|
|
nodecore.set_loud(apos,
|
|
{name = modname .. ":tree_bud", param2 = 1})
|
|
nodecore.witness(apos, "tree growth")
|
|
return nodecore.soaking_abm_push(apos,
|
|
"treegrow", data.total - sproutcost)
|
|
end
|
|
return growparticles(pos, data.rate, 0.2)
|
|
end
|
|
})
|
|
|
|
local function leafbud(pos, dx, dy, dz, param2, surplus, rate)
|
|
local npos = {x = pos.x + dx, y = pos.y + dy, z = pos.z + dz}
|
|
if not nodecore.buildable_to(npos) then
|
|
local node = minetest.get_node(npos)
|
|
if minetest.get_item_group(node.name, "canopy") == 0 or param2 < node.param2
|
|
then return end
|
|
end
|
|
if param2 <= 1 then
|
|
if 240 < math_random(0, 255) then return end
|
|
return nodecore.set_loud(npos, nodecore.calc_leaves(npos))
|
|
end
|
|
nodecore.set_loud(npos, {name = modname .. ":leaves_bud", param2 = param2})
|
|
minetest.get_meta(npos):set_float("growrate", rate)
|
|
return nodecore.soaking_abm_push(npos, "leafgrow", surplus)
|
|
end
|
|
|
|
local trunkcost = 1000
|
|
nodecore.register_soaking_abm({
|
|
label = "tree trunk grow",
|
|
fieldname = "treegrow",
|
|
nodenames = {modname .. ":tree_bud"},
|
|
interval = 10,
|
|
arealoaded = 1,
|
|
soakrate = function(pos, ...)
|
|
local v = nodecore.tree_trunk_growth_rate(pos, ...)
|
|
if v == false then
|
|
minetest.set_node(pos, {name = modname .. ":tree"})
|
|
end
|
|
return v
|
|
end,
|
|
soakcheck = function(data, pos, node)
|
|
if data.total < trunkcost then
|
|
return growparticles(pos, data.rate, 0.45)
|
|
end
|
|
|
|
local tp = nodecore.tree_params[node.param2]
|
|
if not tp then return minetest.remove_node(pos) end
|
|
|
|
minetest.set_node(pos, {name = modname .. ":tree"})
|
|
|
|
local apos = {x = pos.x, y = pos.y + 1, z = pos.z}
|
|
if not nodecore.buildable_to(apos)
|
|
and minetest.get_item_group(minetest.get_node(apos).name, "canopy") == 0
|
|
then return end
|
|
|
|
local param2 = node.param2 + 1
|
|
tp = nodecore.tree_params[param2]
|
|
if not tp then return minetest.remove_node(pos) end
|
|
while tp.prob and (tp.prob < math_random(0, 255)) do
|
|
param2 = param2 + 1
|
|
tp = nodecore.tree_params[param2]
|
|
if not tp then return minetest.remove_node(pos) end
|
|
end
|
|
|
|
local surplus = data.total - trunkcost
|
|
if tp.leaves then
|
|
leafbud(apos, 1, 0, 0, tp.leaves + 1, surplus, data.rate)
|
|
leafbud(apos, -1, 0, 0, tp.leaves + 1, surplus, data.rate)
|
|
leafbud(apos, 0, 0, 1, tp.leaves, surplus, data.rate)
|
|
leafbud(apos, 0, 0, -1, tp.leaves, surplus, data.rate)
|
|
end
|
|
|
|
if tp.notrunk then
|
|
leafbud(apos, 0, 0, 0, tp.leaves, surplus, data.rate)
|
|
else
|
|
nodecore.set_loud(apos, {
|
|
name = modname .. ":tree_bud",
|
|
param2 = param2
|
|
})
|
|
nodecore.witness(apos, "tree growth")
|
|
nodecore.soaking_abm_push(apos,
|
|
"treegrow", surplus)
|
|
end
|
|
end
|
|
})
|
|
|
|
local leafcost = trunkcost
|
|
nodecore.register_soaking_abm({
|
|
label = "tree leaves grow",
|
|
nodenames = {modname .. ":leaves_bud"},
|
|
fieldname = "leafgrow",
|
|
interval = 10,
|
|
arealoaded = 1,
|
|
soakrate = function(pos)
|
|
local rate = minetest.get_meta(pos):get_float("growrate") or 0
|
|
return rate and rate ~= 0 and rate or 10
|
|
end,
|
|
soakcheck = function(data, pos, node)
|
|
if data.total < leafcost then return end
|
|
|
|
nodecore.set_loud(pos, nodecore.calc_leaves(pos))
|
|
|
|
local surplus = data.total - leafcost
|
|
if node.param2 <= 1 then
|
|
return
|
|
elseif node.param2 == 2 then
|
|
leafbud(pos, 1, 0, 0, 1, surplus, data.rate)
|
|
leafbud(pos, -1, 0, 0, 1, surplus, data.rate)
|
|
elseif node.param2 == 3 then
|
|
leafbud(pos, 0, 0, 1, 1, surplus, data.rate)
|
|
leafbud(pos, 0, 0, -1, 1, surplus, data.rate)
|
|
else
|
|
leafbud(pos, 1, 0, 0, 3, surplus, data.rate)
|
|
leafbud(pos, -1, 0, 0, 3, surplus, data.rate)
|
|
leafbud(pos, 0, 0, 1, 2, surplus, data.rate)
|
|
leafbud(pos, 0, 0, -1, 2, surplus, data.rate)
|
|
if node.param2 >= 6 then
|
|
leafbud(pos, 0, 1, 0, node.param2 - 4, surplus, data.rate)
|
|
end
|
|
end
|
|
end
|
|
})
|
|
|
|
local growtreedata = {
|
|
[modname .. ":eggcorn_planted"] = {
|
|
r = nodecore.tree_growth_rate,
|
|
f = "eggcorn"
|
|
},
|
|
[modname .. ":tree_bud"] = {
|
|
r = nodecore.tree_trunk_growth_rate,
|
|
f = "treegrow"
|
|
},
|
|
[modname .. ":leaves_bud"] = {
|
|
r = function() return 1 end,
|
|
f = "leafgrow"
|
|
}
|
|
}
|
|
minetest.register_chatcommand("growtrees", {
|
|
description = "Accelerate growth of nearby trees",
|
|
privs = {["debug"] = true},
|
|
func = function(pname)
|
|
local player = minetest.get_player_by_name(pname)
|
|
if not player then return end
|
|
local pos = player:get_pos()
|
|
local spec = {}
|
|
for k in pairs(growtreedata) do spec[#spec + 1] = k end
|
|
local grew = {}
|
|
for _, p in pairs(nodecore.find_nodes_around(pos, spec, 5)) do
|
|
local nn = minetest.get_node(p).name
|
|
local data = growtreedata[nn]
|
|
local r = data.r(p)
|
|
if r and r > 0 then
|
|
nodecore.soaking_abm_push(p, data.f, 100000)
|
|
grew[#grew + 1] = nn .. " at " .. minetest.pos_to_string(p)
|
|
end
|
|
end
|
|
return true, table_concat(grew, "\n")
|
|
end
|
|
})
|
|
|
|
nodecore.register_craft({
|
|
label = "tickle eggcorn",
|
|
action = "pummel",
|
|
toolgroups = {crumbly = 1},
|
|
normal = {y = 1},
|
|
nodes = {
|
|
{match = {name = modname .. ":eggcorn_planted", stacked = false}}
|
|
},
|
|
after = function(pos)
|
|
nodecore.soaking_abm_tickle(pos, "eggcorn")
|
|
nodecore.soaking_particles(pos, 25, 0.5, .45, modname .. ":leaves_bud")
|
|
end
|
|
})
|
|
|
|
nodecore.register_craft({
|
|
label = "tickle tree trunk",
|
|
action = "pummel",
|
|
toolgroups = {snappy = 1},
|
|
normal = {y = 1},
|
|
nodes = {
|
|
{match = {name = modname .. ":tree_bud", stacked = false}}
|
|
},
|
|
after = function(pos)
|
|
nodecore.soaking_abm_tickle(pos, "treegrow")
|
|
nodecore.soaking_particles(pos, 25, 0.5, .45, modname .. ":leaves_bud")
|
|
end
|
|
})
|
|
|
|
nodecore.register_craft({
|
|
label = "tickle tree leaves",
|
|
action = "pummel",
|
|
toolgroups = {snappy = 1},
|
|
nodes = {
|
|
{match = {name = modname .. ":leaves_bud", stacked = false}}
|
|
},
|
|
after = function(pos)
|
|
nodecore.soaking_abm_tickle(pos, "leafgrow")
|
|
end
|
|
})
|