From fd181833f449cd4ca691fbb3e7155a07ba7cd3fb Mon Sep 17 00:00:00 2001 From: Aaron Suen Date: Thu, 19 Aug 2021 22:19:27 -0400 Subject: [PATCH] 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. --- mods/nc_api/util_misc.lua | 23 +++++++++++ mods/nc_api_craft/fx_smoke.lua | 73 +++++++++++++++++++--------------- mods/nc_fire/abm.lua | 22 ++-------- 3 files changed, 68 insertions(+), 50 deletions(-) diff --git a/mods/nc_api/util_misc.lua b/mods/nc_api/util_misc.lua index f0e199f0..04cb2fb7 100644 --- a/mods/nc_api/util_misc.lua +++ b/mods/nc_api/util_misc.lua @@ -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 diff --git a/mods/nc_api_craft/fx_smoke.lua b/mods/nc_api_craft/fx_smoke.lua index 3b052928..4fe1b1c5 100644 --- a/mods/nc_api_craft/fx_smoke.lua +++ b/mods/nc_api_craft/fx_smoke.lua @@ -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 diff --git a/mods/nc_fire/abm.lua b/mods/nc_fire/abm.lua index f21853d5..9f53e135 100644 --- a/mods/nc_fire/abm.lua +++ b/mods/nc_fire/abm.lua @@ -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)