165 lines
5.2 KiB
Lua
165 lines
5.2 KiB
Lua
local function round(x)
|
|
if x >= 0 then
|
|
return math.floor(x+0.5)
|
|
else
|
|
return math.ceil(x-0.5)
|
|
end
|
|
end
|
|
|
|
local function wakeup(pos,share)
|
|
--called to test if a node needs to be woken up
|
|
local node = minetest.get_node(pos)
|
|
if (minetest.get_item_group(node.name, "sparktech_energy_wakeup") >= 1) then
|
|
local ntype = minetest.get_item_group(node.name, "spaktech_energy_type")
|
|
local meta = minetest.get_meta(pos)
|
|
local energy = meta:get_int("energy")
|
|
if (energy == share) then return end -- only makes sense if we actually change the energy in the block
|
|
if ntype == 2 then
|
|
if energy == 0 then
|
|
minetest.get_node_timer(pos):start(0.5)
|
|
end
|
|
elseif ntype == 4 then
|
|
if minetest.get_item_group(node.name, "sparktech_energy_wakeup") == energy then -- set the value to when you want to be woken up key
|
|
minetest.get_node_timer(pos):start(0.5)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- 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 net_get_slaves(master)
|
|
local slaves = {}
|
|
local meta = minetest.get_meta(master)
|
|
local slave_s = meta:get_string("net_master")
|
|
slave_s = string.sub(slave_s, 2)
|
|
local slave_s_dict = string.split(slave_s, "|")
|
|
for _, val in pairs(slave_s_dict) do
|
|
local cor = string.split(val, ":")
|
|
slaves[#slaves + 1] = { x=tonumber(cor[1]), y=tonumber(cor[2]), z=tonumber(cor[3])}
|
|
end
|
|
return slaves
|
|
end
|
|
|
|
local function net_distribute(pos)
|
|
-- sparktech_energy_type types:
|
|
-- 2 - Producer (gets emptied)
|
|
-- 3 - Storage (backup / overflow)
|
|
-- 4 - Consumer (gets filled)
|
|
|
|
local nodes = net_get_slaves(pos)
|
|
nodes[#nodes +1] = pos
|
|
-- all nodes are in local now
|
|
|
|
-- Gather all information we need for the three node types
|
|
local energy_pr = 0
|
|
local energy_st = 0
|
|
local energy_co = 0
|
|
local max_energy_pr = 0
|
|
local max_energy_st = 0
|
|
local max_energy_co = 0
|
|
for x = 1, #nodes do
|
|
local ntype = minetest.get_item_group(minetest.get_node(nodes[x]).name, "sparktech_energy_type")
|
|
local nenergy = minetest.get_meta(nodes[x]):get_int("energy")
|
|
local nenergy_max = minetest.get_item_group(minetest.get_node(nodes[x]).name, "sparktech_energy_max")
|
|
if ntype == 2 then
|
|
energy_pr = energy_pr + nenergy
|
|
max_energy_pr = max_energy_pr + nenergy_max
|
|
elseif ntype == 3 then
|
|
energy_st = energy_st + nenergy
|
|
max_energy_st = max_energy_st + nenergy_max
|
|
elseif ntype == 4 then
|
|
energy_co = energy_co + nenergy
|
|
max_energy_co = max_energy_co + nenergy_max
|
|
end
|
|
end
|
|
|
|
-- now we know all energy in the system, now to distribute it
|
|
|
|
local pr_new = energy_pr
|
|
local st_new = energy_st
|
|
local co_new = energy_co
|
|
|
|
-- How much energy is available to be put into storage / is missing to fill up the consumers
|
|
local prod_buf = energy_pr - (max_energy_co - energy_co)
|
|
|
|
-- Producers -> Consumers transfer
|
|
if prod_buf >= 0 then
|
|
-- Fill up the consumers to their limit
|
|
pr_new = prod_buf
|
|
co_new = co_new + (energy_pr - prod_buf)
|
|
else
|
|
-- Empty the producers into the consumers
|
|
pr_new = 0
|
|
co_new = co_new + energy_pr
|
|
end
|
|
|
|
-- Storage -> Consumers and Producers -> Storage transfers
|
|
if prod_buf < 0 then
|
|
-- Fill up the consumers with energy in storage
|
|
local sto_buf = energy_st + prod_buf
|
|
if sto_buf >= 0 then
|
|
st_new = sto_buf
|
|
co_new = co_new + energy_st - sto_buf
|
|
else
|
|
st_new = 0
|
|
co_new = co_new + energy_st
|
|
end
|
|
else
|
|
-- Store excess energy into storage
|
|
local st_cap = max_energy_st - energy_st
|
|
if st_cap >= prod_buf then
|
|
pr_new = 0
|
|
st_new = st_new + prod_buf
|
|
else
|
|
pr_new = prod_buf - st_cap
|
|
st_new = st_new + st_cap
|
|
end
|
|
end
|
|
|
|
-- Now the new energy distribution is known
|
|
|
|
-- Apply the later to be improved (maybe) share system to all node types
|
|
local share_pr = pr_new / max_energy_pr;
|
|
local share_st = st_new / max_energy_st;
|
|
local share_co = co_new / max_energy_co;
|
|
for x = 1, #nodes do
|
|
local meta = minetest.get_meta(nodes[x])
|
|
local node = minetest.get_node(nodes[x])
|
|
local ntype = minetest.get_item_group(node.name, "sparktech_energy_type")
|
|
local nmax = minetest.get_item_group(node.name, "sparktech_energy_max")
|
|
if ntype == 2 then --produces
|
|
wakeup(nodes[x], round(share_pr * nmax)) -- TODO: test this
|
|
meta:set_int("energy", round(share_pr * nmax))
|
|
elseif ntype == 3 then --stores
|
|
meta:set_int("energy", round(share_st * nmax))
|
|
elseif ntype == 4 then --consumes
|
|
wakeup(nodes[x], round(share_co * nmax))
|
|
meta:set_int("energy", round(share_co * nmax))
|
|
end
|
|
end
|
|
end
|
|
|
|
local function filter(pos)-- function is called severall times, only run if this is a master node
|
|
local meta = minetest.get_meta(pos)
|
|
local net_master = meta:get_string("net_master")
|
|
if (net_master == nil or net_master == "") then -- if it is not set this is NOT a master node, so we can ignore it eh
|
|
return
|
|
else
|
|
net_distribute(pos)
|
|
end
|
|
end
|
|
|
|
minetest.register_abm({
|
|
nodenames = {"group:sparktech_net_trigger"},
|
|
interval = 1.0,
|
|
chance = 1,
|
|
catch_up = true,
|
|
action = function(pos, node, active_object_count, active_object_count_wider)
|
|
filter(pos)
|
|
end
|
|
})
|