Aaron Suen 166cfe5f14 Mitigate excess server block sends
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.
2022-08-24 20:44:14 -04:00

120 lines
2.9 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local ipairs, math, minetest, nodecore, pairs, vector
= ipairs, math, minetest, nodecore, pairs, vector
local math_random
= math.random
-- LUALOCALS > ---------------------------------------------------------
local modname = minetest.get_current_modname()
local sparks_add, sparks_flush = nodecore.fairlimit(50)
nodecore.register_globalstep("fire sparks", function()
for _, pos in ipairs(sparks_flush()) do
minetest.after(math_random(), function()
minetest.add_particlespawner({
amount = math_random(1, 3),
time = 1,
minpos = vector.subtract(pos, 0.5),
maxpos = vector.add(pos, 0.5),
minvel = {x = -1, y = 2, z = -1},
maxvel = {x = 1, y = 2.5, z = 1},
minacc = {x = -0.1, y = 0, z = -0.1},
maxacc = {x = 0.1, y = 0, z = 0.1},
minxeptime = 1,
maxexptime = 3,
minsize = 0.1,
maxsize = 0.2,
collisiondetection = true,
collision_removal = true,
texture = "nc_fire_spark.png",
glow = math_random(5, 9)
})
end)
end
end)
do
local flamedirs = nodecore.dirs()
local embers = {}
minetest.after(0, function()
for k, v in pairs(minetest.registered_items) do
if v.groups.ember then
embers[k] = true
end
end
end)
minetest.register_abm({
label = "fire consume",
interval = 1,
chance = 1,
arealoaded = 1,
nodenames = {modname .. ":fire"},
action = function(pos)
sparks_add(pos)
local found = {}
for _, dp in ipairs(flamedirs) do
local npos = vector.add(pos, dp)
local node = minetest.get_node_or_nil(npos)
if (not node) or embers[node.name] then
found[#found + 1] = npos
end
end
if #found < 1 then
return minetest.remove_node(pos)
end
local picked = nodecore.pickrand(found)
return nodecore.fire_check_expend(picked)
end
})
end
minetest.register_abm({
label = "flammables ignite",
interval = 5,
chance = 1,
nodenames = {"group:flammable"},
neighbors = {"group:igniter"},
neighbors_invert = true,
arealoaded = 1,
action_delay = true,
action = function(pos)
nodecore.fire_check_ignite(pos)
end
})
minetest.register_abm({
label = "ember snuff/flames",
interval = 1,
chance = 1,
nodenames = {"group:ember"},
arealoaded = 1,
action = function(pos, node)
local snuff, vents = nodecore.fire_check_snuff(pos, node)
if snuff or not vents then return end
for i = 1, #vents do
if vents[i].q < 1 then
nodecore.set_node_check(vents[i], {name = modname .. ":fire"})
end
end
end
})
nodecore.register_ambiance({
label = "flame ambiance",
nodenames = {"group:flame_ambiance"},
interval = 1,
chance = 1,
sound_name = "nc_fire_flamy",
sound_gain = 0.2
})
nodecore.register_item_ambiance({
label = "flame ambiance",
itemnames = {"group:flame_ambiance"},
interval = 1,
chance = 1,
sound_name = "nc_fire_flamy",
sound_gain = 0.1
})