This repository has been archived on 2020-05-24. You can view files and clone it, but cannot push or open issues or pull requests.
minetest-mod-sparktech/sparkcore/lua/energy.lua

142 lines
6.2 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- internal var net_master stores all slave nodes
-- sparktech_net_passive = are used to follow nets, do not count towards energy
-- sparktech_net_trigger = trigger updates
-- Updates blocks every seconds
local function compare_vec(va, vb)
if va == nil or vb == nil then
return false
end
return va.x == vb.x and va.y == vb.y and va.z == vb.z
end
local function add_node_to_net(pos, master) -- stores node in master meta
local meta = minetest.get_meta(master)
-- format x:y:z|x2:y2:z2
local net_master = meta:get_string("net_master")
net_master = net_master .. "|" .. pos.x .. ":" .. pos.y .. ":" .. pos.z;
meta:set_string("net_master", net_master)
local slavem = minetest.get_meta(pos)
slavem:set_string("net_master", "")
end
-- All nodes processed in a build cycle
-- Keeping track of caller nodes alone allows duplication
local processed = {}
-- The master of the network should not be limited to one branch
local master = nil
local function net_build(pos, callerpos, master_arg)
-- Option to force the master node
if (master_arg ~= nil) then
master = master_arg
end
local onode = minetest.get_node(pos)
-- Add node to the list of processed nodes so that it wont be processed again
-- A node can show up multiple times in this list!
processed[#processed + 1] = pos
-- LOGIC to check only x sides, can be done eventually lol
-- e.g furnace only allows from below , or solar panels
-- before this need api to make cables connect from those side only too! otherwise it makes no sense for viewers
-- in game
local top = {x = pos.x, y = pos.y + 1, z = pos.z}
local bottom = {x = pos.x, y = pos.y - 1, z = pos.z}
local left = {x = pos.x - 1, y = pos.y, z = pos.z}
local right = {x = pos.x + 1, y = pos.y, z = pos.z}
local front = {x = pos.x, y = pos.y, z = pos.z - 1}
local back = {x = pos.x, y = pos.y, z = pos.z + 1}
-- if at this point master is set to "none" the master is NOT known!
-- in this case for every next block it has to be checked if it is a suitable master, if it is place your stuff in it
for sidename, nodepos in pairs({top=top, bottom=bottom, left=left, right=right, front=front, back=back}) do -- as long as the order of directions is ok its ok
-- if the position has already been processed ignore it
local already_processed = false
for _, cpos in pairs(processed) do
if compare_vec(cpos, nodepos) then
already_processed = true
break
end
end
if (not already_processed) then
local node = minetest.get_node(nodepos)
local meta = minetest.get_meta(nodepos)
local net_passive = minetest.get_item_group(node.name,"sparktech_net_passive")
if (net_passive == 0 and meta:get_int("sparktech_net_passive") == 1) then
net_passive = 1
end
local net_trigger = minetest.get_item_group(node.name,"sparktech_net_trigger")
-- net passives are followed along to create the network (aka cables) but they do not get power,
-- and are not considered by the network
-- TODO recursion
local ntrigontrig = (net_trigger == 1 and (minetest.get_item_group(onode.name, "sparktech_net_trigger") == 0)) -- Only allow trigger node if the source node it not a trigger node
if (net_trigger == 1 and master == nil) then
master = nodepos;
meta:set_string("net_master", nil)
end -- if no master is set the code will just run around checking for one, if it doesnt find one well, doesnt matter, its just cables then
if (master ~= nil and ntrigontrig and nodepos ~= master) then -- we have a master, so we can store stuff in it :D
meta:set_string("net_master", nil)
-- the node is a trigger, so we store their stuff in the master node
-- at this point it could be the master if we set it above
add_node_to_net(nodepos, master) -- we set all relevant data for this node, lets continue there
-- Now the node shouldnt be processed by the net_build anymore
processed[#processed + 1] = nodepos
end
if (net_passive ~= 0 or ntrigontrig) then
net_build(nodepos, pos)
end
end
end
-- To have a clear enviroment for the next build we clear the processed list at the final return
-- TODO This will cause problems if another network is build before the previous network finishes building
-- Only the node triggering a build wont have a caller
if (callerpos == nil) then
processed = {}
master = nil
end
return -- at this point all nodes have been processed, so we can return to the calling node
end
local function add_node(pos, newnode)
local meta = minetest.get_meta(pos)
if (minetest.get_item_group(newnode.name, "sparktech_net_passive") == 1 or meta:get_int("sparktech_net_passive") ~= 0) then
net_build(pos) -- only call this with none if the node really is not a trigger, otherwise the net will be build from it but it will not be contained
elseif (minetest.get_item_group(newnode.name, "sparktech_net_trigger") == 1 ) then
meta:set_string("net_master", nil)
net_build(pos, nil, pos)
end
end
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
add_node(pos, newnode)
end)
local function remove_node(pos, oldnode)
if (minetest.get_item_group(oldnode.name, "sparktech_net_passive") == TRUE) or (minetest.get_item_group(oldnode.name, "sparktech_net_trigger") == TRUE) then
minetest.debug("removing nodes...")
local top = {x = pos.x, y = pos.y + 1, z = pos.z}
local bottom = {x = pos.x, y = pos.y - 1, z = pos.z}
local left = {x = pos.x - 1, y = pos.y, z = pos.z}
local right = {x = pos.x + 1, y = pos.y, z = pos.z}
local front = {x = pos.x, y = pos.y, z = pos.z - 1}
local back = {x = pos.x, y = pos.y, z = pos.z + 1}
for sidename, nodepos in pairs({top=top, bottom=bottom, left=left, right=right, front=front, back=back}) do
local target_node = minetest.get_node(nodepos)
add_node(nodepos, target_node)
end
end
end
minetest.register_on_dignode(function(pos, oldnode, digger)
remove_node(pos, oldnode) -- FIXME Get rid of this! Somehow detect if a dynamic net_passive node is destroyed instead of updating speculatively
-- TODO: I am not sure what this is for, just to get every dig in general? but we already dont allow those nodes to be dug, so dunno
end)
sparktech.add_node_to_net = add_node
sparktech.remove_node_from_net = remove_node