2019-03-04 23:49:16 -05:00
|
|
|
-- LUALOCALS < ---------------------------------------------------------
|
2019-12-03 08:01:33 -05:00
|
|
|
local math, minetest, nodecore, pairs, vector
|
|
|
|
= math, minetest, nodecore, pairs, vector
|
|
|
|
local math_random
|
|
|
|
= math.random
|
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-12-03 07:57:22 -05:00
|
|
|
local function scan(pos, dir, max)
|
2019-03-05 23:05:56 -05:00
|
|
|
local p = {x = pos.x, y = pos.y, z = pos.z}
|
2019-12-03 07:57:22 -05:00
|
|
|
if (not max) or (max > 16) then max = 16 end
|
|
|
|
for _ = 1, max do
|
2019-03-05 23:05:56 -05:00
|
|
|
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-11-23 08:57:03 -05:00
|
|
|
if def.groups and def.groups.visinv then
|
|
|
|
local stack = nodecore.stack_get(p)
|
|
|
|
def = minetest.registered_items[stack:get_name()]
|
|
|
|
if def and def.type == "node" and not def.sunlight_propagates then
|
|
|
|
return p, node
|
|
|
|
end
|
|
|
|
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-12-03 07:57:22 -05:00
|
|
|
local function optic_trigger(start, dir, max)
|
|
|
|
local pos, node = scan(start, dir, max)
|
2019-03-07 01:40:26 -05:00
|
|
|
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)
|
2019-03-24 19:52:14 -04:00
|
|
|
if node.name == "ignore" then return end
|
2019-03-04 23:49:16 -05:00
|
|
|
local def = minetest.registered_items[node.name] or {}
|
2019-03-07 00:58:37 -05:00
|
|
|
|
2019-03-24 18:24:37 -04:00
|
|
|
local ignored
|
2019-03-07 00:35:27 -05:00
|
|
|
if def and def.optic_check then
|
|
|
|
local func = function(dir)
|
2019-08-31 09:26:53 -04:00
|
|
|
local hit, hnode = scan_recv(pos, dir)
|
2019-03-24 18:24:37 -04:00
|
|
|
ignored = ignored or hit == false
|
2019-08-31 09:26:53 -04:00
|
|
|
return hit, hnode
|
2019-03-07 00:35:27 -05:00
|
|
|
end
|
2019-03-24 18:24:37 -04:00
|
|
|
local nn, res = def.optic_check(pos, node, func, def)
|
2019-03-24 23:15:25 -04:00
|
|
|
if (not ignored) and nn then
|
2019-03-12 20:30:59 -04:00
|
|
|
trans[minetest.hash_node_position(pos)] = {
|
|
|
|
pos = pos,
|
|
|
|
nn = nn,
|
2019-12-03 07:57:22 -05:00
|
|
|
data = res
|
2019-03-12 20:30:59 -04:00
|
|
|
}
|
2019-03-07 00:35:27 -05:00
|
|
|
end
|
|
|
|
end
|
2019-03-04 23:49:16 -05:00
|
|
|
end
|
|
|
|
|
2019-03-12 20:30:59 -04:00
|
|
|
local function optic_commit(v)
|
2019-12-03 07:57:22 -05:00
|
|
|
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
|
2019-03-12 20:30:59 -04:00
|
|
|
local node = minetest.get_node(v.pos)
|
|
|
|
if node.name ~= v.nn then
|
|
|
|
node.name = v.nn
|
|
|
|
minetest.set_node(v.pos, node)
|
2019-12-03 07:57:22 -05:00
|
|
|
updated = true
|
2019-03-12 20:30:59 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
local data = {}
|
2019-08-31 09:26:53 -04:00
|
|
|
for _, vv in pairs(v.data or {}) do
|
|
|
|
data[dirname(vv)] = 1
|
2019-03-12 20:30:59 -04:00
|
|
|
end
|
|
|
|
|
2019-12-03 07:57:22 -05:00
|
|
|
local dirty
|
2019-03-12 20:30:59 -04:00
|
|
|
for _, dir in pairs(nodecore.dirs()) do
|
|
|
|
local dn = dirname(dir)
|
|
|
|
if old[dn] ~= data[dn] then
|
|
|
|
optic_trigger(v.pos, dir)
|
2019-12-03 07:57:22 -05:00
|
|
|
dirty = true
|
|
|
|
elseif updated then
|
|
|
|
optic_trigger(v.pos, dir, 1)
|
2019-08-27 19:14:51 -04:00
|
|
|
end
|
2019-03-12 20:30:59 -04:00
|
|
|
end
|
2019-12-03 07:57:22 -05:00
|
|
|
if dirty then
|
|
|
|
meta:set_string("nc_optics", minetest.serialize(data))
|
|
|
|
end
|
2019-03-12 20:30:59 -04:00
|
|
|
end
|
|
|
|
|
2019-12-03 08:01:33 -05:00
|
|
|
local passive_queue = {}
|
|
|
|
minetest.register_abm({
|
2020-06-17 07:09:20 -04:00
|
|
|
label = "optic check",
|
2019-12-03 08:01:33 -05:00
|
|
|
interval = 1,
|
|
|
|
chance = 1,
|
|
|
|
nodenames = {"group:optic_check"},
|
|
|
|
action = function(pos)
|
|
|
|
passive_queue[#passive_queue + 1] = pos
|
|
|
|
end
|
|
|
|
})
|
|
|
|
|
|
|
|
local passive_batch = {}
|
2020-06-15 07:21:39 -04:00
|
|
|
nodecore.register_globalstep("optic check", function()
|
2019-03-04 23:49:16 -05:00
|
|
|
local batch = optic_queue
|
|
|
|
optic_queue = {}
|
2019-03-07 00:35:27 -05:00
|
|
|
|
2019-12-03 08:01:33 -05:00
|
|
|
if #passive_queue > 0 then
|
|
|
|
passive_batch = passive_queue
|
|
|
|
passive_queue = {}
|
|
|
|
for i = 1, #passive_batch do
|
|
|
|
local j = math_random(1, #passive_batch)
|
|
|
|
local t = passive_batch[i]
|
|
|
|
passive_batch[i] = passive_batch[j]
|
|
|
|
passive_batch[j] = t
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local max = 25 - #batch
|
|
|
|
if max < 5 then max = 5 end
|
|
|
|
if max > #passive_batch then max = #passive_batch end
|
|
|
|
for _ = 1, max do
|
|
|
|
local pos = passive_batch[#passive_batch]
|
|
|
|
passive_batch[#passive_batch] = nil
|
|
|
|
batch[minetest.hash_node_position(pos)] = pos
|
|
|
|
end
|
|
|
|
|
2019-03-12 20:30:59 -04:00
|
|
|
local trans = {}
|
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
|
|
|
|
|
2019-03-12 20:30:59 -04:00
|
|
|
for _, v in pairs(trans) do
|
|
|
|
optic_commit(v)
|
2019-03-04 23:49:16 -05:00
|
|
|
end
|
|
|
|
end)
|