Network fixes - Powercells/Batteries

- Powercells/Batteries now distribute power when Powergen for network is 0
- Powercells/Batteries will only distribute power to "Active" machines lowering network drain
- All machines/Powercells-Batteries act as power pass through ie no longer a network end point - note this only happened on reload of game they worked like this when laid out this way just game save/reload caused machines/Powercells to act as end point.
- fixed Issue max_stack to stack_max, https://gitlab.icynet.eu/evert/elepower/-/issues/5
This commit is contained in:
Sirrobzeroone 2021-06-14 08:29:25 +10:00
parent e489f0c714
commit 2627e0c763
5 changed files with 191 additions and 69 deletions

View File

@ -4,10 +4,17 @@ ele.register_conduit("elepower_dynamics:conduit", {
description = "Power Conduit",
tiles = {"elepower_conduit.png"},
use_texture_alpha = "clip",
ele_conductor_density = 1/8,
groups = {oddly_breakable_by_hand = 1, cracky = 1}
})
--[[
ele.register_conduit("elepower_dynamics:conduit_wall", {
description = "Power Conduit Wall Pass Through",
tiles = {"elepower_machine_side.png^elepower_power_port.png"},
use_texture_alpha = "clip",
ele_conductor_density = 4/8,
groups = {oddly_breakable_by_hand = 1, cracky = 1}
})
--]]
-- Fluid
fluid_lib.register_transfer_node("elepower_dynamics:opaque_duct", {
description = "Opaque Fluid Duct",

View File

@ -38,7 +38,6 @@ function elepm.register_storage(nodename, nodedef)
nodedef.groups["ele_machine"] = 1
nodedef.groups["ele_storage"] = 1
nodedef.groups["ele_provider"] = 1
nodedef.groups["tubedevice"] = 1
nodedef.groups["tubedevice_receiver"] = 1

View File

@ -32,7 +32,7 @@ minetest.register_craftitem("elepower_nuclear:nuclear_waste", {
minetest.register_craftitem("elepower_nuclear:fuel_rod_empty", {
description = "Empty Fuel Rod",
inventory_image = "elenuclear_fuel_rod_empty.png",
max_stack = 1,
stack_max = 1,
})
minetest.register_craftitem("elepower_nuclear:fuel_rod_fissile", {
@ -40,13 +40,13 @@ minetest.register_craftitem("elepower_nuclear:fuel_rod_fissile", {
inventory_image = "elenuclear_fuel_rod_fissile.png",
groups = { fissile_fuel = 1 },
fissile_count = 7200,
max_stack = 1,
stack_max = 1,
})
minetest.register_craftitem("elepower_nuclear:fuel_rod_depleted", {
description = "Depleted Fuel Rod\nCan not be used in a reactor anymore",
inventory_image = "elenuclear_fuel_rod_depleted.png",
max_stack = 1,
stack_max = 1,
})
-- Control rods
@ -54,19 +54,19 @@ minetest.register_craftitem("elepower_nuclear:fuel_rod_depleted", {
minetest.register_craftitem("elepower_nuclear:control_rod", {
description = "Control Rod",
inventory_image = "elenuclear_control_rod.png",
max_stack = 4,
stack_max = 4,
})
minetest.register_craftitem("elepower_nuclear:control_rod_assembly", {
description = "Control Rod Assembly",
inventory_image = "elenuclear_control_rod_assembly.png",
max_stack = 1,
stack_max = 1,
})
minetest.register_craftitem("elepower_nuclear:control_plate", {
description = "Perforated Control Plate",
inventory_image = "elenuclear_control_plate.png",
max_stack = 1,
stack_max = 1,
})
-- Pressure vessel
@ -74,7 +74,7 @@ minetest.register_craftitem("elepower_nuclear:control_plate", {
minetest.register_craftitem("elepower_nuclear:pressure_vessel", {
description = "Reactor Pressure Vessel",
inventory_image = "elenuclear_pressure_vessel.png",
max_stack = 1,
stack_max = 1,
})
--------------------------

View File

@ -257,8 +257,9 @@ function ele.register_base_device(nodename, nodedef)
-- Override destruct callback
local original_after_destruct = nodedef.after_destruct
nodedef.after_destruct = function (pos)
ele.clear_networks(pos)
if original_after_destruct then
original_after_destruct(pos)
end

View File

@ -1,10 +1,7 @@
-- Network graphs are built eminating from provider nodes.
--[[
TODO:
Currently, there's a problem where storage nodes are allowed to create their own graph.
When placing the storage onto a cable, it will add itself to the graph of that cable.
But, when placing a cable onto the storage, that cable is added to the storage's own graph
and thus cannot be connected to the previous graph.
Power taken from power providers is not balanced so all power comes from
1st provider in table then 2nd 3rd...etc needs balancing like users.
]]
-- Network cache
@ -23,7 +20,7 @@ local function table_has_string(arr, str)
return false
end
local function add_node(nodes, pos, pnodeid)
local function add_node(nodes, pos, pnodeid, group)
local node_id = minetest.hash_node_position(pos)
if not ele.graphcache.devices[node_id] then
@ -39,6 +36,10 @@ local function add_node(nodes, pos, pnodeid)
end
nodes[node_id] = pos
if group ~= nil then
nodes[node_id].group = group
end
return true
end
@ -57,6 +58,7 @@ local function check_node(users, providers, conductors, pos, pr_pos, pnodeid, qu
if ele.helpers.get_item_group(node.name, "ele_conductor") then
add_conductor_node(conductors, pos, pnodeid, queue)
--minetest.debug("C2"..minetest.pos_to_string(pos))
return
end
@ -64,11 +66,23 @@ local function check_node(users, providers, conductors, pos, pr_pos, pnodeid, qu
return
end
if ele.helpers.get_item_group(node.name, "ele_user") or
ele.helpers.get_item_group(node.name, "ele_storage") then
add_node(users, pos, pnodeid)
if ele.helpers.get_item_group(node.name, "ele_user") then
if add_node(users, pos, pnodeid) then
queue[#queue + 1] = pos
--minetest.debug("M2"..minetest.pos_to_string(pos))
end
elseif ele.helpers.get_item_group(node.name, "ele_storage") then
if add_node(users, pos, pnodeid, "ele_storage") then
queue[#queue + 1] = pos
--minetest.debug("S2"..minetest.pos_to_string(pos))
end
elseif ele.helpers.get_item_group(node.name, "ele_provider") then
add_node(providers, pos, pnodeid)
if add_node(providers, pos, pnodeid) then
queue[#queue + 1] = pos
--minetest.debug("P2"..minetest.pos_to_string(pos))
end
end
end
@ -81,6 +95,8 @@ local function traverse_network(users, providers, conductors, pos, pr_pos, pnode
{x=pos.x, y=pos.y, z=pos.z+1},
{x=pos.x, y=pos.y, z=pos.z-1}}
for _, cur_pos in pairs(positions) do
-- if node already in table then dont add
check_node(users, providers, conductors, cur_pos, pr_pos, pnodeid, queue)
end
end
@ -105,8 +121,10 @@ local function discover_branches(pr_pos, positions)
local node = minetest.get_node(pos)
if node and ele.helpers.get_item_group(node.name, "ele_conductor") then
add_conductor_node(conductors, pos, pnodeid, queue)
--minetest.debug("C "..minetest.pos_to_string(pos))
elseif node and ele.helpers.get_item_group(node.name, "ele_machine") then
queue = {pr_pos}
--minetest.debug("M "..minetest.pos_to_string(pr_pos))
end
while next(queue) do
@ -119,7 +137,7 @@ local function discover_branches(pr_pos, positions)
end
-- Add self to providers
add_node(providers, pr_pos, pnodeid)
add_node(providers, pr_pos, pnodeid)
users = ele.helpers.flatten(users)
providers = ele.helpers.flatten(providers)
@ -139,7 +157,9 @@ local function give_node_power(pos, available)
local capacity = ele.helpers.get_node_property(user_meta, pos, "capacity")
local inrush = ele.helpers.get_node_property(user_meta, pos, "inrush")
local storage = user_meta:get_int("storage")
local usage = ele.helpers.get_node_property(user_meta, pos, "usage")
local status = user_meta:get_string("infotext")
local total_add = 0
if available >= inrush then
@ -157,7 +177,7 @@ local function give_node_power(pos, available)
storage = capacity
end
return total_add, storage
return total_add, storage, usage, status
end
@ -174,7 +194,6 @@ minetest.register_abm({
local providers = {}
local providerdef = minetest.registered_nodes[node.name]
-- TODO: Customizable output sides
local positions = {
{x=pos.x, y=pos.y-1, z=pos.z},
@ -191,10 +210,11 @@ minetest.register_abm({
local name = pnode.name
local networked = ele.helpers.get_item_group(name, "ele_machine") or
ele.helpers.get_item_group(name, "ele_conductor")
if networked then
branches[#branches + 1] = pos1
end
--minetest.debug(name.." "..tostring(networked).." :B"..#branches)
end
-- No possible branches found
@ -208,9 +228,10 @@ minetest.register_abm({
-- Find all users and providers
users, providers = discover_branches(pos, branches)
-- Calculate power data
local pw_supply = 0
local pw_demand = 0
-- Calculate power data for providers
local pw_supply = 0
local pw_demand = 0
local bat_supply = 0
for _, spos in ipairs(providers) do
local smeta = minetest.get_meta(spos)
@ -219,24 +240,85 @@ minetest.register_abm({
if p_output and pw_storage >= p_output then
pw_supply = pw_supply + p_output
elseif p_output and pw_storage < p_output then
pw_supply = pw_supply + pw_storage
end
end
-- Power Cells / Batteries
-- Calculate power data for batteries
-- set two override tables to remove batteries from
-- users and make them providers.
local bat_flag = false
local bat_users = {}
local bat_providers = {}
-- Providers all give power on 1st provider hit by abm, then there pr_pos
-- power avaliable is set to 0. We dont want batteries running on this
-- secondary + abm hits. On 1st pass a meta value is set on all providers
-- "dep_time" - depleted time, just a simple os.clock timestamp.
local dep_timer = true
local time_since_dep = os.clock() - meta:get_int("dep_time") or 0
if time_since_dep < 1 then
dep_timer = false
end
if pw_supply == 0 and dep_timer == true then
for k,pg in pairs(users) do -- pg = pos and group
if pg.group == "ele_storage" then
local bpos = {x = pg.x, y = pg.y, z = pg.z}
local smeta = minetest.get_meta(bpos)
local bat_storage = smeta:get_int("storage")
local bat_output = ele.helpers.get_node_property(smeta, bpos, "output")
table.insert(bat_providers, pg) -- save node_users who are batteries to providers
if bat_output and bat_storage >= bat_output then
bat_supply = bat_supply + bat_output
elseif bat_output and bat_storage < bat_output then
bat_supply = bat_supply + bat_storage
end
else
table.insert(bat_users, pg) -- save node_users who aren't batteries
end
end
users = bat_users -- replace users with bat_users so batteries arent users anymore
providers = bat_providers -- replace providers with bat_providers
pw_supply = bat_supply -- override with battery supply
bat_flag = true
end
-- Give power to users
local divide_power = {}
for _,ndv in ipairs(users) do --ndv = pos table
-- Check how much power a node wants and can get ie is it close to full charge
local user_gets, user_storage = give_node_power(ndv, (pw_supply - pw_demand))
-- Add the node_users wanting power to table for later power division
if user_gets > 0 then
table.insert(divide_power,{pos = ndv,user_gets = user_gets, user_storage = user_storage})
local user_gets, user_storage, user_usage, user_status = give_node_power(ndv, (pw_supply - pw_demand)) -- pw_demand always 0 check old code
-- when on battery we dont want to provide user_inrush or if
-- machine is currently not in use we dont want to use bat power
-- user_status provides the tooltip info when you point at a
-- machine, only intrested in "Active", any value but "nil" indicates
-- the word "Active" was found.
if bat_flag == true then
local active = string.find(user_status, "Active")
if active ~= nil then
if user_gets > user_usage then
user_gets = user_usage
end
else
user_gets = 0
end
end
-- Add the node_users wanting power to table for later power division
if user_gets > 0 then
table.insert(divide_power,{pos = ndv,user_gets = user_gets, user_storage = user_storage})
end
end
-- The below shares avaliable power from a network between node_users
@ -244,45 +326,44 @@ minetest.register_abm({
-- the first few node_users. If divided power is less than 1 the
-- network is overloaded and delivers no power to any nodes.
-- A node_user can recieve power from two different networks
-- if pw_supply ~= 0 then minetest.debug(node.name.." - Power Supplied: "..pw_supply) end --debug line
-- if pw_supply ~= 0 then minetest.debug(node.name.." - Power Can Supply: "..pw_supply) end --debug line
local num_users = #divide_power
local div_pwr = pw_supply/num_users
local whole_pwr_num = math.floor(div_pwr)
local remainder_pwr_num = (math.fmod(div_pwr,1))*num_users
if div_pwr < 1 then
num_users = 0 -- network overload
end
local i = 1
while(num_users >= i)do
while(num_users >= i)do
local final_pwr_num
if remainder_pwr_num > 0.5 then
final_pwr_num = whole_pwr_num + 1
remainder_pwr_num = remainder_pwr_num - 1
else
final_pwr_num = whole_pwr_num
final_pwr_num = whole_pwr_num
end
if final_pwr_num > divide_power[i].user_gets then
if final_pwr_num > divide_power[i].user_gets then
final_pwr_num = divide_power[i].user_gets
end
--minetest.debug("node_user "..minetest.pos_to_string(divide_power[i].pos).." Power Supplied:"..final_pwr_num) -- debug line
-- minetest.debug("node_user "..minetest.pos_to_string(divide_power[i].pos).." Power Supplied:"..final_pwr_num) -- debug line
local user_meta = minetest.get_meta(divide_power[i].pos)
user_meta:set_int("storage", divide_power[i].user_storage + final_pwr_num)
pw_demand = pw_demand + final_pwr_num
ele.helpers.start_timer(divide_power[i].pos)
i = i+1
i = i+1
end
-- Take the power from provider nodes
if pw_demand > 0 then
@ -299,10 +380,16 @@ minetest.register_abm({
smeta:set_int("storage", 0)
end
if bat_flag == false then
smeta:set_int("dep_time", os.clock())
end
ele.helpers.start_timer(spos)
end
end
--if pw_supply ~= 0 then minetest.debug("end_run") end -- debug line
-- if pw_supply ~= 0 then minetest.debug("end_run") end -- debug line
minetest.debug(dump(ele.graphcache)) -- network dump
end,
})
@ -336,17 +423,17 @@ function ele.clear_networks(pos)
local placed = name ~= "air"
local positions = check_connections(pos)
if #positions < 1 then return end
local hash_pos = minetest.hash_node_position(pos)
local dead_end = #positions == 1
for _,connected_pos in ipairs(positions) do
local networks = ele.graphcache.devices[minetest.hash_node_position(connected_pos)] or
{minetest.pos_to_string(connected_pos)}
for _,net in ipairs(networks) do
if net and ele.graphcache[net] then
if net and ele.graphcache[net] then
-- This is so we can break the pipeline instead of the network search loop
while true do
if dead_end and placed then
@ -373,14 +460,42 @@ function ele.clear_networks(pos)
table.insert(ele.graphcache.devices[hash_pos], int_net)
end
-- local function to check if value exists in network tables
-- required as each provider has its own network so placed node
-- can end up inside overall network grps two or more times
local function check_exists(table_sub,pos)
local exist = false
local tpos_string
local pos_string
for k,v in ipairs(table_sub) do
-- we have group on some of these so need to
-- manually create tpos cant just use v
tpos_string = minetest.pos_to_string({x=v.x,y=v.y,z=v.z})
pos_string = minetest.pos_to_string(pos)
if tpos_string == pos_string then
exist = true
end
end
return exist
end
if ele.helpers.get_item_group(name, "ele_conductor") then
table.insert(network.conductors, pos)
--minetest.debug("check : "..tostring(check_exists(network.conductors,pos))) -- debug line
if not check_exists(network.users,pos) then
table.insert(network.conductors,pos)
end
elseif ele.helpers.get_item_group(name, "ele_machine") then
if ele.helpers.get_item_group(name, "ele_user") or
if ele.helpers.get_item_group(name, "ele_user") or
ele.helpers.get_item_group(name, "ele_storage") then
table.insert(network.users, pos)
if not check_exists(network.users,pos) then
table.insert(network.users, pos)
end
elseif ele.helpers.get_item_group(name, "ele_provider") then
table.insert(network.providers, pos)
if not check_exists(network.providers, pos) then
table.insert(network.providers, pos)
end
end
end
end
@ -410,7 +525,7 @@ function ele.clear_networks(pos)
ele.graphcache.devices[pos1] = nil
end
ele.graphcache[int_net] = nil
else
-- Search for and remove device
-- This checks and removes from network.users,
@ -435,11 +550,11 @@ function ele.clear_networks(pos)
local pos1 = minetest.hash_node_position(v)
ele.graphcache.devices[pos1] = nil
end
ele.graphcache[net] = nil
ele.graphcache[net] = nil
break
end
break
end
end
end
end
end