Limit smoke effects, e.g. from concrete cure

Standardize a "fair limiting" mechanism that
limits the items accepted into a queue, and
returns a uniform random sample when flushed.

Pass all cooking/curing smoke effects into fair
limit queue.

Apply fairl limit queue to fire sparks too.

Pliant concrete curing checks still seem to lag
the server somewhat, but at least now they
shouldn't hammer the client with particles and
kill framerate too.
This commit is contained in:
Aaron Suen 2021-08-19 22:19:27 -04:00
parent 22ff675761
commit fd181833f4
3 changed files with 68 additions and 50 deletions

View File

@ -41,6 +41,29 @@ function nodecore.mkreg()
return f, t
end
function nodecore.fairlimit(max)
local queue = {}
local qty = 0
local function add(item)
qty = qty + 1
if qty > max then
local id = math_random(1, qty)
if id <= max then
queue[id] = item
end
else
queue[qty] = item
end
end
local function flush()
local batch = queue
queue = {}
qty = 0
return batch
end
return add, flush
end
function nodecore.memoize(func)
local cachedval
local cached

View File

@ -1,41 +1,50 @@
-- LUALOCALS < ---------------------------------------------------------
local math, minetest, nodecore, type
= math, minetest, nodecore, type
local ipairs, math, minetest, nodecore, type
= ipairs, math, minetest, nodecore, type
local math_random
= math.random
-- LUALOCALS > ---------------------------------------------------------
local smoke_add, smoke_flush = nodecore.fairlimit(50)
local smoking = {}
nodecore.register_globalstep("smoke queue", function()
for _, item in ipairs(smoke_flush()) do
local pos, qty, time = item.pos, item.qty, item.time
local now = minetest.get_us_time() / 1000000
local key = minetest.hash_node_position(pos)
local old = smoking[key]
if old and now < old.exp then minetest.delete_particlespawner(old.id) end
if (not time) or (time <= 0) then
smoking[key] = nil
return
end
if type(qty) ~= "number" then qty = 1 end
if qty < 1 then
if math_random() > qty then return end
qty = 1
end
smoking[key] = {
id = minetest.add_particlespawner({
texture = "nc_api_craft_smoke.png",
collisiondetection = true,
amount = (qty or 2) * time,
time = time,
minpos = {x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4},
maxpos = {x = pos.x + 0.4, y = pos.y + 0.4, z = pos.z + 0.4},
minvel = {x = -0.1, y = 0.3, z = -0.1},
maxvel = {x = 0.1, y = 0.7, z = 0.1},
minexptime = 1,
maxexptime = 5,
minsize = 1,
maxsize = 3
}),
exp = now + time
}
end
end)
function nodecore.smokefx(pos, time, qty)
local now = minetest.get_us_time() / 1000000
local key = minetest.hash_node_position(pos)
local old = smoking[key]
if old and now < old.exp then minetest.delete_particlespawner(old.id) end
if (not time) or (time <= 0) then
smoking[key] = nil
return
end
if type(qty) ~= "number" then qty = 1 end
if qty < 1 then
if math_random() > qty then return end
qty = 1
end
smoking[key] = {
id = minetest.add_particlespawner({
texture = "nc_api_craft_smoke.png",
collisiondetection = true,
amount = (qty or 2) * time,
time = time,
minpos = {x = pos.x - 0.4, y = pos.y - 0.4, z = pos.z - 0.4},
maxpos = {x = pos.x + 0.4, y = pos.y + 0.4, z = pos.z + 0.4},
minvel = {x = -0.1, y = 0.3, z = -0.1},
maxvel = {x = 0.1, y = 0.7, z = 0.1},
minexptime = 1,
maxexptime = 5,
minsize = 1,
maxsize = 3
}),
exp = now + time
}
return smoke_add({pos = pos, time = time, qty = qty})
end

View File

@ -7,13 +7,10 @@ local math_random
local modname = minetest.get_current_modname()
local sparks = {}
local sparkqty = 0
local sparkmax = 50
local sparks_add, sparks_flush = nodecore.fairlimit(50)
nodecore.register_globalstep("fire sparks", function()
if sparkqty < 1 then return end
for i = 1, #sparks do
local pos = sparks[i]
for _, pos in ipairs(sparks_flush()) do
minetest.after(math_random(), function()
minetest.add_particlespawner({
amount = math_random(1, 3),
@ -35,8 +32,6 @@ nodecore.register_globalstep("fire sparks", function()
})
end)
end
sparks = {}
sparkqty = 0
end)
do
@ -55,16 +50,7 @@ do
chance = 1,
nodenames = {modname .. ":fire"},
action = function(pos)
sparkqty = sparkqty + 1
if sparkqty > sparkmax then
local sparkid = math_random(1, sparkqty)
if sparkid <= sparkmax then
sparks[sparkid] = pos
end
else
sparks[sparkqty] = pos
end
sparks_add(pos)
local found = {}
for _, dp in ipairs(flamedirs) do
local npos = vector.add(pos, dp)