Fix major optics performance bug.

Optic checks were being propagated unconditionally in loops,
causing nearly every node in an optic network to be checked every
time.

This restores behavior to the original intended behavior of
propagating forward changes on next tick, but stopping at points
where state quiesces.

Unfortunately beam obstruction sensing has been working
instantaneously because of this bug, and that will revert to the
original intended behavior of having those picked up only on
random checks, which may cause regressions in some builds.
This commit is contained in:
Aaron Suen 2019-12-03 07:57:22 -05:00
parent c8a4f3d369
commit 4ee34d4b2d
2 changed files with 22 additions and 16 deletions

View File

@ -14,6 +14,9 @@ ISSUES: Bugs, Cleanup and Refinements
- Reverse lens active/shining bias, favor shining.
- Solar activation issues are too surprising.
- Probably should be using hash_node_position insted of pos_to_string
in many places where we don't support non-integer positions anyway
- Living Sponge Overhaul Gen3
- Easily harvest living sponges as living
- Living sponges die quickly over time if taken out of water

View File

@ -15,9 +15,10 @@ local function dirname(pos)
return ""
end
local function scan(pos, dir)
local function scan(pos, dir, max)
local p = {x = pos.x, y = pos.y, z = pos.z}
for _ = 1, 16 do
if (not max) or (max > 16) then max = 16 end
for _ = 1, max do
p = vector.add(p, dir)
local node = minetest.get_node(p)
if node.name == "ignore" then return false, node end
@ -48,8 +49,8 @@ local function optic_check(pos)
end
nodecore.optic_check = optic_check
local function optic_trigger(start, dir)
local pos, node = scan(start, dir)
local function optic_trigger(start, dir, max)
local pos, node = scan(start, dir, max)
if not node then return end
local def = minetest.registered_items[node.name] or {}
if def and def.optic_check then return optic_check(pos) end
@ -72,23 +73,23 @@ local function optic_process(trans, pos)
trans[minetest.hash_node_position(pos)] = {
pos = pos,
nn = nn,
data = res or {}
data = res
}
end
end
if not ignored then
for _, dir in pairs(nodecore.dirs()) do
optic_trigger(pos, dir)
end
end
end
local function optic_commit(v)
local meta = minetest.get_meta(v.pos)
local old = meta:get_string("nc_optics")
old = old and (old ~= "") and minetest.deserialize(old) or {}
local updated
local node = minetest.get_node(v.pos)
if node.name ~= v.nn then
node.name = v.nn
minetest.set_node(v.pos, node)
updated = true
end
local data = {}
@ -96,17 +97,19 @@ local function optic_commit(v)
data[dirname(vv)] = 1
end
local meta = minetest.get_meta(v.pos)
local old = meta:get_string("nc_optics")
old = old and minetest.deserialize(old) or {}
local dirty
for _, dir in pairs(nodecore.dirs()) do
local dn = dirname(dir)
if old[dn] ~= data[dn] then
optic_trigger(v.pos, dir)
dirty = true
elseif updated then
optic_trigger(v.pos, dir, 1)
end
end
meta:set_string("nc_optics", minetest.serialize(data))
if dirty then
meta:set_string("nc_optics", minetest.serialize(data))
end
end
minetest.register_globalstep(function()