From 7fd51c1a6c49fea0bff5d8ee146b207a27c9fdaa Mon Sep 17 00:00:00 2001 From: Aaron Suen Date: Sun, 21 Mar 2021 12:08:08 -0400 Subject: [PATCH] ABM "inversion" API This is useful when we want to perform an action on a commonly-occuring node (like sand or item stacks) with a requirement of a neighbor of a less common node type (like igniters). Checking for B with A nearby can be a lot faster than A with B nearby if B is less common, so fewer neighbor checks actually need to happen. This was already done "manually" for the flammable/igniter interaction, but now this is a general API for all ABMs, that allows the inversion to be done nearly transparently with just a flag in the definition, and so the ABM rules can be written more simply, with the inversion handled elsewhere. TODO: Rewrite current manual-inversions, including the ones for flammable/igniter and lava/stone hardening/softening. --- mods/nc_api_active/abminvert.lua | 43 ++++++++++++++++++++++++++++++++ mods/nc_api_active/init.lua | 1 + 2 files changed, 44 insertions(+) create mode 100644 mods/nc_api_active/abminvert.lua diff --git a/mods/nc_api_active/abminvert.lua b/mods/nc_api_active/abminvert.lua new file mode 100644 index 00000000..be821568 --- /dev/null +++ b/mods/nc_api_active/abminvert.lua @@ -0,0 +1,43 @@ +-- LUALOCALS < --------------------------------------------------------- +local ipairs, minetest, nodecore, pairs + = ipairs, minetest, nodecore, pairs +-- LUALOCALS > --------------------------------------------------------- + +local hash = minetest.hash_node_position + +local oldreg = minetest.register_abm +function minetest.register_abm(def, ...) + if not def.neighbors_invert then return oldreg(def, ...) end + + local nnames = def.nodenames + def.nodenames = def.neighbors + def.neighbors = nnames + + local oldact = def.action + + local queue + local function process() + for _, v in pairs(queue) do + local nnode = minetest.get_node(v.pos) + if nnode.name == v.node.name then + oldact(v.pos, nnode) + end + end + queue = nil + end + + function def.action(pos) + if not queue then + queue = {} + minetest.after(0, process) + end + for _, npos in ipairs(nodecore.find_nodes_around(pos, nnames, 1)) do + queue[hash(pos)] = { + pos = npos, + node = minetest.get_node(npos) + } + end + end + + return oldreg(def, ...) +end diff --git a/mods/nc_api_active/init.lua b/mods/nc_api_active/init.lua index 56e3bb89..3cd3e771 100644 --- a/mods/nc_api_active/init.lua +++ b/mods/nc_api_active/init.lua @@ -8,6 +8,7 @@ nodecore.amcoremod() nodecore.register_limited_abm = function(...) return minetest.register_abm(...) end include("abmmux") +include("abminvert") include("stasis") include("dnts") include("aism")