2019-03-04 23:49:16 -05:00
|
|
|
-- LUALOCALS < ---------------------------------------------------------
|
2019-03-07 22:27:38 -05:00
|
|
|
local error, minetest, nodecore, pairs, pcall, vector
|
|
|
|
= error, minetest, nodecore, pairs, pcall, vector
|
2019-03-04 23:49:16 -05:00
|
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
|
2019-03-05 23:05:56 -05:00
|
|
|
local optic_queue = {}
|
2019-03-04 23:49:16 -05:00
|
|
|
|
2019-03-07 00:35:27 -05:00
|
|
|
local function dirname(pos)
|
|
|
|
if pos.x > 0 then return "e" end
|
|
|
|
if pos.x < 0 then return "w" end
|
|
|
|
if pos.y > 0 then return "u" end
|
|
|
|
if pos.y < 0 then return "d" end
|
|
|
|
if pos.z > 0 then return "n" end
|
|
|
|
if pos.z < 0 then return "s" end
|
|
|
|
return ""
|
|
|
|
end
|
|
|
|
|
2019-03-05 23:05:56 -05:00
|
|
|
local function scan(pos, dir)
|
|
|
|
local p = {x = pos.x, y = pos.y, z = pos.z}
|
|
|
|
for i = 1, 16 do
|
|
|
|
p = vector.add(p, dir)
|
|
|
|
local node = minetest.get_node(p)
|
2019-03-07 00:35:27 -05:00
|
|
|
if node.name == "ignore" then return false, node end
|
2019-03-09 19:46:52 -05:00
|
|
|
local def = minetest.registered_items[node.name] or {}
|
|
|
|
if not def.sunlight_propagates then return p, node end
|
2019-03-05 23:05:56 -05:00
|
|
|
end
|
2019-03-04 23:49:16 -05:00
|
|
|
end
|
|
|
|
|
2019-03-07 00:35:27 -05:00
|
|
|
local function scan_recv(pos, dir)
|
|
|
|
local hit, node = scan(pos, dir)
|
|
|
|
if not hit then return hit, node end
|
|
|
|
local data = minetest.get_meta(hit):get_string("nc_optics")
|
|
|
|
if data == "" then return end
|
|
|
|
dir = dirname(vector.multiply(dir, -1))
|
|
|
|
if not minetest.deserialize(data)[dir] then return end
|
|
|
|
return hit, node
|
2019-03-05 23:05:56 -05:00
|
|
|
end
|
2019-03-04 23:49:16 -05:00
|
|
|
|
2019-03-07 00:35:27 -05:00
|
|
|
local function optic_check(pos)
|
2019-03-04 23:49:16 -05:00
|
|
|
optic_queue[minetest.hash_node_position(pos)] = pos
|
|
|
|
end
|
2019-03-07 00:35:27 -05:00
|
|
|
nodecore.optic_check = optic_check
|
2019-03-04 23:49:16 -05:00
|
|
|
|
2019-03-07 01:40:26 -05:00
|
|
|
local function optic_trigger(start, dir)
|
|
|
|
local pos, node = scan(start, dir)
|
|
|
|
if not node then return end
|
2019-03-07 00:35:27 -05:00
|
|
|
local def = minetest.registered_items[node.name] or {}
|
|
|
|
if def and def.optic_check then return optic_check(pos) end
|
2019-03-04 23:49:16 -05:00
|
|
|
end
|
|
|
|
|
2019-03-12 20:22:42 -04:00
|
|
|
local function optic_process(trans, pos)
|
2019-03-04 23:49:16 -05:00
|
|
|
local node = minetest.get_node(pos)
|
|
|
|
local def = minetest.registered_items[node.name] or {}
|
2019-03-07 00:58:37 -05:00
|
|
|
|
2019-03-07 00:35:27 -05:00
|
|
|
if def and def.optic_check then
|
|
|
|
local func = function(dir)
|
|
|
|
local hit, node = scan_recv(pos, dir)
|
2019-03-07 01:56:27 -05:00
|
|
|
if hit == false then error("IgNoReArEa") end
|
2019-03-07 00:35:27 -05:00
|
|
|
return hit, node
|
|
|
|
end
|
2019-03-07 01:40:26 -05:00
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local old = meta:get_string("nc_optics")
|
2019-03-12 20:22:42 -04:00
|
|
|
local ok, nn, res = pcall(def.optic_check, pos, node, func, def)
|
2019-03-07 00:35:27 -05:00
|
|
|
if ok then
|
|
|
|
local data = {}
|
|
|
|
for k, v in pairs(res or {}) do
|
|
|
|
data[dirname(v)] = 1
|
|
|
|
end
|
2019-03-07 01:40:26 -05:00
|
|
|
|
|
|
|
old = old and minetest.deserialize(old) or {}
|
|
|
|
for _, dir in pairs(nodecore.dirs()) do
|
|
|
|
local dn = dirname(dir)
|
|
|
|
if old[dn] ~= data[dn] then
|
|
|
|
optic_trigger(pos, dir)
|
|
|
|
end
|
2019-03-07 00:58:37 -05:00
|
|
|
end
|
2019-03-07 01:40:26 -05:00
|
|
|
|
2019-03-12 20:22:42 -04:00
|
|
|
local key = minetest.hash_node_position(pos)
|
|
|
|
trans.nodes[key] = {pos = pos, nn = nn}
|
|
|
|
trans.meta[key] = {pos = pos, data = data}
|
|
|
|
elseif nn:match("IgNoReArEa") then
|
2019-03-07 01:56:27 -05:00
|
|
|
minetest.log("optic check for "
|
|
|
|
.. minetest.pos_to_string(pos)
|
|
|
|
.. " hit unloaded area")
|
|
|
|
else
|
2019-03-07 00:35:27 -05:00
|
|
|
error(res)
|
|
|
|
end
|
|
|
|
end
|
2019-03-07 00:58:37 -05:00
|
|
|
|
2019-03-05 23:05:56 -05:00
|
|
|
for _, dir in pairs(nodecore.dirs()) do
|
2019-03-07 01:40:26 -05:00
|
|
|
optic_trigger(pos, dir)
|
2019-03-04 23:49:16 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
minetest.register_globalstep(function()
|
|
|
|
-- snapshot batch, as processing may write to queue
|
|
|
|
local batch = optic_queue
|
|
|
|
optic_queue = {}
|
2019-03-07 00:35:27 -05:00
|
|
|
|
2019-03-12 20:22:42 -04:00
|
|
|
local trans = {nodes = {}, meta = {}}
|
2019-03-04 23:49:16 -05:00
|
|
|
for _, pos in pairs(batch) do
|
2019-03-12 20:22:42 -04:00
|
|
|
optic_process(trans, pos)
|
|
|
|
end
|
|
|
|
|
|
|
|
for _, v in pairs(trans.nodes) do
|
|
|
|
local node = minetest.get_node(v.pos)
|
|
|
|
if node.name ~= v.nn then
|
|
|
|
node.name = v.nn
|
|
|
|
minetest.set_node(v.pos, node)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
for _, v in pairs(trans.meta) do
|
|
|
|
minetest.get_meta(v.pos):set_string("nc_optics",
|
|
|
|
minetest.serialize(v.data))
|
2019-03-04 23:49:16 -05:00
|
|
|
end
|
|
|
|
end)
|
2019-03-07 00:35:27 -05:00
|
|
|
|
|
|
|
nodecore.register_limited_abm({
|
|
|
|
label = "Optic Check",
|
2019-03-07 01:56:27 -05:00
|
|
|
interval = 1,
|
2019-03-07 00:35:27 -05:00
|
|
|
chance = 1,
|
|
|
|
limited_max = 100,
|
|
|
|
limited_alert = 100,
|
|
|
|
nodenames = {"group:optic_check"},
|
|
|
|
action = nodecore.optic_check
|
|
|
|
})
|