From 2627e0c7635e56f24f029e9977a66ae7d6f47e38 Mon Sep 17 00:00:00 2001 From: Sirrobzeroone <44497598+sirrobzeroone@users.noreply.github.com> Date: Mon, 14 Jun 2021 08:29:25 +1000 Subject: [PATCH] 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 --- elepower_dynamics/conduits.lua | 11 +- elepower_machines/machines/bases/storage.lua | 1 - elepower_nuclear/craftitems.lua | 14 +- elepower_papi/machine.lua | 3 +- elepower_papi/network.lua | 231 ++++++++++++++----- 5 files changed, 191 insertions(+), 69 deletions(-) diff --git a/elepower_dynamics/conduits.lua b/elepower_dynamics/conduits.lua index e1a67b3..8a6d452 100644 --- a/elepower_dynamics/conduits.lua +++ b/elepower_dynamics/conduits.lua @@ -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", diff --git a/elepower_machines/machines/bases/storage.lua b/elepower_machines/machines/bases/storage.lua index 31e132f..315b3e9 100644 --- a/elepower_machines/machines/bases/storage.lua +++ b/elepower_machines/machines/bases/storage.lua @@ -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 diff --git a/elepower_nuclear/craftitems.lua b/elepower_nuclear/craftitems.lua index a802806..302c019 100644 --- a/elepower_nuclear/craftitems.lua +++ b/elepower_nuclear/craftitems.lua @@ -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, }) -------------------------- diff --git a/elepower_papi/machine.lua b/elepower_papi/machine.lua index d71d228..6abfa8b 100644 --- a/elepower_papi/machine.lua +++ b/elepower_papi/machine.lua @@ -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 diff --git a/elepower_papi/network.lua b/elepower_papi/network.lua index 8a23e2a..bb3a668 100644 --- a/elepower_papi/network.lua +++ b/elepower_papi/network.lua @@ -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