Remove metadata for supply,demand,battery_count,battery_charge,battery_charge_max

Remove switching station from networks

Disable few debug prints, add removed machines to LBM

clear_networks refatoring #95

Functions remove_network_node and add_network_branch #95

Fix undef network_id, remove flatten #95
This commit is contained in:
SX 2020-09-26 04:37:20 +03:00
parent c08732cd87
commit f66c644fce
8 changed files with 299 additions and 206 deletions

View File

@ -35,6 +35,7 @@ function technic.sw_pos2tier(pos, use_vm)
return technic.get_cable_tier(minetest.get_node(cable_pos).name) return technic.get_cable_tier(minetest.get_node(cable_pos).name)
end end
-- Destroy network data
function technic.remove_network(network_id) function technic.remove_network(network_id)
local cables = technic.cables local cables = technic.cables
for pos_hash,cable_net_id in pairs(cables) do for pos_hash,cable_net_id in pairs(cables) do
@ -43,7 +44,23 @@ function technic.remove_network(network_id)
end end
end end
technic.networks[network_id] = nil technic.networks[network_id] = nil
print(string.format("NET DESTRUCT %s (%.17g)", minetest.pos_to_string(technic.network2pos(network_id)), network_id)) --print(string.format("NET DESTRUCT %s (%.17g)", minetest.pos_to_string(technic.network2pos(network_id)), network_id))
end
-- Remove machine or cable from network
local network_node_tables = {"PR_nodes","BA_nodes","RE_nodes","SP_nodes","all_nodes"}
function technic.remove_network_node(network_id, pos)
local network = technic.networks[network_id]
if not network then return end
technic.cables[poshash(pos)] = nil
for _,tblname in ipairs(network_node_tables) do
local table = network[tblname]
for id,mpos in pairs(table) do
if mpos.x == pos.x and mpos.y == pos.y and mpos.z == pos.z then
table[id] = nil
end
end
end
end end
function technic.sw_pos2network(pos) function technic.sw_pos2network(pos)
@ -104,6 +121,11 @@ local overload_reset_time = tonumber(minetest.settings:get("technic.overload_res
local overloaded_networks = {} local overloaded_networks = {}
function technic.overload_network(network_id) function technic.overload_network(network_id)
local network = technic.networks[network_id]
if network then
network.supply = 0
network.battery_charge = 0
end
overloaded_networks[network_id] = minetest.get_us_time() + (overload_reset_time * 1000 * 1000) overloaded_networks[network_id] = minetest.get_us_time() + (overload_reset_time * 1000 * 1000)
end end
@ -125,13 +147,6 @@ end
-- --
-- Functions to traverse the electrical network -- Functions to traverse the electrical network
-- --
local function flatten(map)
local list = {}
for key, value in pairs(map) do
list[#list + 1] = value
end
return list
end
local function attach_network_machine(network_id, pos) local function attach_network_machine(network_id, pos)
local pos_hash = poshash(pos) local pos_hash = poshash(pos)
@ -148,31 +163,26 @@ local function attach_network_machine(network_id, pos)
end end
end end
-- Add a wire node to the LV/MV/HV network -- Add a machine node to the LV/MV/HV network
local function add_network_node(nodes, pos, network_id) local function add_network_node(nodes, pos, network_id)
technic.cables[poshash(pos)] = network_id
table.insert(nodes, pos)
end
-- Add a wire node to the LV/MV/HV network
local function add_cable_node(nodes, pos, network_id, queue)
local node_id = poshash(pos) local node_id = poshash(pos)
technic.cables[node_id] = network_id technic.cables[node_id] = network_id
if nodes[node_id] then if nodes[node_id] then
return false return false
end end
nodes[node_id] = pos nodes[node_id] = pos
return true -- Also add cables to queue
end queue[#queue + 1] = pos
local function add_cable_node(nodes, pos, network_id, queue)
if add_network_node(nodes, pos, network_id) then
queue[#queue + 1] = pos
end
end end
-- Generic function to add found connected nodes to the right classification array -- Generic function to add found connected nodes to the right classification array
local function check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, pos, machines, tier, sw_pos, from_below, network_id, queue) local function check_node_subp(PR_nodes, RE_nodes, BA_nodes, all_nodes, pos, machines, tier, sw_pos, from_below, network_id, queue)
local distance_to_switch = vector.distance(pos, sw_pos)
if distance_to_switch > switch_max_range then
-- max range exceeded
return
end
technic.get_or_load_node(pos) technic.get_or_load_node(pos)
local name = minetest.get_node(pos).name local name = minetest.get_node(pos).name
@ -192,10 +202,6 @@ local function check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes
--attach_network_machine(network_id, pos) --attach_network_machine(network_id, pos)
add_network_node(PR_nodes, pos, network_id) add_network_node(PR_nodes, pos, network_id)
add_network_node(RE_nodes, pos, network_id) add_network_node(RE_nodes, pos, network_id)
elseif machines[name] == "SPECIAL" and from_below then
-- Another switching station -> disable it
attach_network_machine(network_id, pos)
add_network_node(SP_nodes, pos, network_id)
elseif machines[name] == technic.battery then elseif machines[name] == technic.battery then
attach_network_machine(network_id, pos) attach_network_machine(network_id, pos)
add_network_node(BA_nodes, pos, network_id) add_network_node(BA_nodes, pos, network_id)
@ -206,7 +212,7 @@ local function check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes
end end
-- Traverse a network given a list of machines and a cable type name -- Traverse a network given a list of machines and a cable type name
local function traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, pos, machines, tier, sw_pos, network_id, queue) local function traverse_network(PR_nodes, RE_nodes, BA_nodes, all_nodes, pos, machines, tier, sw_pos, network_id, queue)
local positions = { local positions = {
{x=pos.x+1, y=pos.y, z=pos.z}, {x=pos.x+1, y=pos.y, z=pos.z},
{x=pos.x-1, y=pos.y, z=pos.z}, {x=pos.x-1, y=pos.y, z=pos.z},
@ -215,7 +221,7 @@ local function traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_node
{x=pos.x, y=pos.y, z=pos.z+1}, {x=pos.x, y=pos.y, z=pos.z+1},
{x=pos.x, y=pos.y, z=pos.z-1}} {x=pos.x, y=pos.y, z=pos.z-1}}
for i, cur_pos in pairs(positions) do for i, cur_pos in pairs(positions) do
check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, cur_pos, machines, tier, sw_pos, i == 3, network_id, queue) check_node_subp(PR_nodes, RE_nodes, BA_nodes, all_nodes, cur_pos, machines, tier, sw_pos, i == 3, network_id, queue)
end end
end end
@ -237,6 +243,28 @@ local function get_network(network_id, tier)
return technic.build_network(network_id) return technic.build_network(network_id)
end end
function technic.add_network_branch(queue, sw_pos, network)
-- Adds whole branch to network, queue positions can be used to bypass sub branches
local PR_nodes = network.PR_nodes -- Indexed array
local BA_nodes = network.BA_nodes -- Indexed array
local RE_nodes = network.RE_nodes -- Indexed array
local all_nodes = network.all_nodes -- Hash table
local network_id = network.id
local tier = network.tier
while next(queue) do
local to_visit = {}
for _, pos in ipairs(queue) do
if vector.distance(pos, sw_pos) > switch_max_range then
-- max range exceeded
return
end
traverse_network(PR_nodes, RE_nodes, BA_nodes, all_nodes, pos,
technic.machines[tier], tier, sw_pos, network_id, to_visit)
end
queue = to_visit
end
end
function technic.build_network(network_id) function technic.build_network(network_id)
print(string.format("NET CONSTRUCT %s (%.17g)", minetest.pos_to_string(technic.network2pos(network_id)), network_id)) print(string.format("NET CONSTRUCT %s (%.17g)", minetest.pos_to_string(technic.network2pos(network_id)), network_id))
technic.remove_network(network_id) technic.remove_network(network_id)
@ -246,29 +274,24 @@ function technic.build_network(network_id)
print(string.format("Cannot build network, cannot get tier for switching station at %s", minetest.pos_to_string(sw_pos))) print(string.format("Cannot build network, cannot get tier for switching station at %s", minetest.pos_to_string(sw_pos)))
return return
end end
local PR_nodes = {} local network = {
local BA_nodes = {} id = network_id, tier = tier, all_nodes = {},
local RE_nodes = {} SP_nodes = {}, PR_nodes = {}, RE_nodes = {}, BA_nodes = {},
local SP_nodes = {} supply = 0, demand = 0, timeout = 4, battery_charge = 0, battery_charge_max = 0,
local all_nodes = {} }
-- Add first cable (one that is holding network id) and build network
local queue = {} local queue = {}
-- Add first cable (one that is holding network id) add_cable_node(network.all_nodes, technic.network2pos(network_id), network_id, queue)
add_cable_node(all_nodes, technic.network2pos(network_id), network_id, queue) technic.add_network_branch(queue, sw_pos, network)
while next(queue) do -- Flatten hashes to optimize iterations
local to_visit = {} --network.PR_nodes = flatten(network.PR_nodes) -- Already processed as indexed array
for _, pos in ipairs(queue) do --network.BA_nodes = flatten(network.BA_nodes) -- Already processed as indexed array
traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, --network.RE_nodes = flatten(network.RE_nodes) -- Already processed as indexed array
pos, technic.machines[tier], tier, sw_pos, network_id, to_visit) network.battery_count = #network.BA_nodes
end -- Add newly built network to cache array
queue = to_visit technic.networks[network_id] = network
end -- And return producers, batteries and receivers (should this simply return network?)
PR_nodes = flatten(PR_nodes) return network.PR_nodes, network.BA_nodes, network.RE_nodes
BA_nodes = flatten(BA_nodes)
RE_nodes = flatten(RE_nodes)
--SP_nodes = flatten(SP_nodes) -- can this be removed from network data?
technic.networks[network_id] = {tier = tier, all_nodes = all_nodes, SP_nodes = SP_nodes,
PR_nodes = PR_nodes, RE_nodes = RE_nodes, BA_nodes = BA_nodes, timeout = 4}
return PR_nodes, BA_nodes, RE_nodes
end end
-- --
@ -315,9 +338,11 @@ function technic.network_run(network_id)
local RE_nodes local RE_nodes
local tier = technic.sw_pos2tier(pos) local tier = technic.sw_pos2tier(pos)
local network
if tier then if tier then
PR_nodes, BA_nodes, RE_nodes = get_network(network_id, tier) PR_nodes, BA_nodes, RE_nodes = get_network(network_id, tier)
if technic.is_overloaded(network_id) then return end if technic.is_overloaded(network_id) then return end
network = technic.networks[network_id]
else else
--dprint("Not connected to a network") --dprint("Not connected to a network")
technic.network_infotext(network_id, S("%s Has No Network"):format(S("Switching Station"))) technic.network_infotext(network_id, S("%s Has No Network"):format(S("Switching Station")))
@ -400,13 +425,12 @@ function technic.network_run(network_id)
S("Switching Station"), technic.EU_string(PR_eu_supply), S("Switching Station"), technic.EU_string(PR_eu_supply),
technic.EU_string(RE_eu_demand))) technic.EU_string(RE_eu_demand)))
local meta = minetest.get_meta(pos)
-- If mesecon signal and power supply or demand changed then -- If mesecon signal and power supply or demand changed then
-- send them via digilines. -- send them via digilines.
if mesecons_path and digilines_path and mesecon.is_powered(pos) then if mesecons_path and digilines_path and mesecon.is_powered(pos) then
if PR_eu_supply ~= meta:get_int("supply") or if PR_eu_supply ~= network.supply or
RE_eu_demand ~= meta:get_int("demand") then RE_eu_demand ~= network.demand then
local meta = minetest.get_meta(pos)
local channel = meta:get_string("channel") local channel = meta:get_string("channel")
digilines.receptor_send(pos, technic.digilines.rules, channel, { digilines.receptor_send(pos, technic.digilines.rules, channel, {
supply = PR_eu_supply, supply = PR_eu_supply,
@ -416,11 +440,11 @@ function technic.network_run(network_id)
end end
-- Data that will be used by the power monitor -- Data that will be used by the power monitor
meta:set_int("supply",PR_eu_supply) network.supply = PR_eu_supply
meta:set_int("demand",RE_eu_demand) network.demand = RE_eu_demand
meta:set_int("battery_count",#BA_nodes) network.battery_count = #BA_nodes
meta:set_int("battery_charge",BA_charge) network.battery_charge = BA_charge
meta:set_int("battery_charge_max",BA_charge_max) network.battery_charge_max = BA_charge_max
-- If the PR supply is enough for the RE demand supply them all -- If the PR supply is enough for the RE demand supply them all
if PR_eu_supply >= RE_eu_demand then if PR_eu_supply >= RE_eu_demand then
@ -533,13 +557,16 @@ if false then
nodenames = { nodenames = {
"group:technic_machine", "group:technic_machine",
"group:technic_all_tiers", "group:technic_all_tiers",
"technic:switching_station",
"technic:power_monitor",
}, },
action = function(pos, node) action = function(pos, node)
-- Delete all listed metadata key/value pairs from technic machines -- Delete all listed metadata key/value pairs from technic machines
local keys = { local keys = {
"LV_EU_timeout", "MV_EU_timeout", "HV_EU_timeout", "LV_EU_timeout", "MV_EU_timeout", "HV_EU_timeout",
"LV_network", "MV_network", "HV_network", "LV_network", "MV_network", "HV_network",
"active_pos", "active_pos", "supply", "demand",
"battery_count", "battery_charge", "battery_charge_max",
} }
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
for _,key in ipairs(keys) do for _,key in ipairs(keys) do

View File

@ -13,6 +13,7 @@ local function get_cable(pos)
end end
-- return the position of connected cable or nil -- return the position of connected cable or nil
-- TODO: Make it support every possible orientation
local function get_connected_cable_network(pos) local function get_connected_cable_network(pos)
local param2 = minetest.get_node(pos).param2 local param2 = minetest.get_node(pos).param2
-- should probably also work sideways or upside down but for now it wont -- should probably also work sideways or upside down but for now it wont
@ -26,18 +27,16 @@ local function get_connected_cable_network(pos)
-- Behind? -- Behind?
checkpos = vector.add(minetest.facedir_to_dir(param2),pos) checkpos = vector.add(minetest.facedir_to_dir(param2),pos)
network_id = get_cable(checkpos) and technic.pos2network(checkpos) network_id = get_cable(checkpos) and technic.pos2network(checkpos)
if network_id then return network_id
return network_id
end
end end
-- return the position of the associated switching station or nil -- return the position of the associated switching station or nil
local function get_swpos(pos) local function get_network(pos)
local network_id = get_connected_cable_network(pos) local network_id = get_connected_cable_network(pos)
local network = network_id and technic.networks[network_id] local network = network_id and technic.networks[network_id]
local swpos = network and technic.network2sw_pos(network_id) local swpos = network and technic.network2sw_pos(network_id)
local is_powermonitor = swpos and minetest.get_node(swpos).name == "technic:switching_station" local is_powermonitor = swpos and minetest.get_node(swpos).name == "technic:switching_station"
return (is_powermonitor and network.all_nodes[network_id]) and swpos return (is_powermonitor and network.all_nodes[network_id]) and network
end end
minetest.register_craft({ minetest.register_craft({
@ -97,19 +96,16 @@ minetest.register_node("technic:power_monitor",{
return return
end end
local sw_pos = get_swpos(pos) local network = get_network(pos)
if not sw_pos then if not network then return end
return
end
local sw_meta = minetest.get_meta(sw_pos)
digilines.receptor_send(pos, technic.digilines.rules, channel, { digilines.receptor_send(pos, technic.digilines.rules, channel, {
supply = sw_meta:get_int("supply"), supply = network.supply,
demand = sw_meta:get_int("demand"), demand = network.demand,
lag = sw_meta:get_int("lag"), lag = network.lag,
battery_count = sw_meta:get_int("battery_count"), battery_count = network.battery_count,
battery_charge = sw_meta:get_int("battery_charge"), battery_charge = network.battery_charge,
battery_charge_max = sw_meta:get_int("battery_charge_max"), battery_charge_max = network.battery_charge_max,
}) })
end end
}, },
@ -123,14 +119,10 @@ minetest.register_abm({
chance = 1, chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider) action = function(pos, node, active_object_count, active_object_count_wider)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local sw_pos = get_swpos(pos) local network = get_network(pos)
if sw_pos then if network then
local sw_meta = minetest.get_meta(sw_pos) meta:set_string("infotext", S("Power Monitor. Supply: @1 Demand: @2",
local supply = sw_meta:get_int("supply") technic.EU_string(network.supply), technic.EU_string(network.demand)))
local demand = sw_meta:get_int("demand")
meta:set_string("infotext",
S("Power Monitor. Supply: @1 Demand: @2",
technic.EU_string(supply), technic.EU_string(demand)))
else else
meta:set_string("infotext",S("Power Monitor Has No Network")) meta:set_string("infotext",S("Power Monitor Has No Network"))
end end

View File

@ -13,6 +13,9 @@ end
local function check_connections(pos) local function check_connections(pos)
-- Build a table of all machines -- Build a table of all machines
-- TODO: Move this to network.lua
-- TODO: Build table for current tier only, we do not want to test other tiers.
-- Make sure that multi tier machines work (currently supply converter).
local machines = {} local machines = {}
for tier,list in pairs(technic.machines) do for tier,list in pairs(technic.machines) do
for k,v in pairs(list) do for k,v in pairs(list) do
@ -36,81 +39,94 @@ local function check_connections(pos)
return connections return connections
end end
local function clear_networks(pos) local function connect_networks(pos, positions)
local node = minetest.get_node(pos) -- TODO: Allow connecting networks:
local placed = node.name ~= "air" -- If neighbor branch does not belong to any network attach it to this network
-- If neighbor branch belongs to another network check which one has least #all_nodes and rebuild that
for _,connected_pos in pairs(positions) do
local net = technic.pos2network(connected_pos)
if net and technic.networks[net] then
-- Not a dead end, so the whole network needs to be recalculated
technic.remove_network(net)
end
end
end
local function place_network_node(pos, node)
local positions = check_connections(pos) local positions = check_connections(pos)
if #positions < 1 then return end if #positions < 1 then return end
local dead_end = #positions == 1 local dead_end = #positions == 1
for _,connected_pos in pairs(positions) do
local net = technic.cables[minetest.hash_node_position(connected_pos)]
if net and technic.networks[net] then
if dead_end and placed then
-- Dead end placed, add it to the network
-- Get the network
local network_id = technic.cables[minetest.hash_node_position(positions[1])]
if not network_id then
-- We're evidently not on a network, nothing to add ourselves to
return
end
local sw_pos = minetest.get_position_from_hash(network_id)
sw_pos.y = sw_pos.y + 1
local network = technic.networks[network_id]
local tier = network.tier
-- Actually add it to the (cached) network -- Dead end placed, add it to the network
-- This is similar to check_node_subp -- Get the network
local pos_hash = minetest.hash_node_position(pos) local network_id = technic.pos2network(positions[1])
technic.cables[pos_hash] = network_id if not network_id then
pos.visited = 1 -- We're evidently not on a network, nothing to add ourselves to
if technic.is_tier_cable(name, tier) then return
network.all_nodes[pos_hash] = pos end
elseif technic.machines[tier][node.name] then local network = technic.networks[network_id]
if technic.machines[tier][node.name] == technic.producer then local tier = network.tier
table.insert(network.PR_nodes,pos)
elseif technic.machines[tier][node.name] == technic.receiver then
table.insert(network.RE_nodes,pos)
elseif technic.machines[tier][node.name] == technic.producer_receiver then
table.insert(network.PR_nodes,pos)
table.insert(network.RE_nodes,pos)
elseif technic.machines[tier][node.name] == "SPECIAL" and
(pos.x ~= sw_pos.x or pos.y ~= sw_pos.y or pos.z ~= sw_pos.z) and
from_below then
network.SP_nodes[pos_hash] = pos
elseif technic.machines[tier][node.name] == technic.battery then
table.insert(network.BA_nodes,pos)
end
end
elseif dead_end and not placed then
-- Dead end removed, remove it from the network
-- Get the network
local network_id = technic.cables[minetest.hash_node_position(positions[1])]
if not network_id then
-- We're evidently not on a network, nothing to add ourselves to
return
end
local network = technic.networks[network_id]
-- Search for and remove machine if not dead_end then
technic.cables[minetest.hash_node_position(pos)] = nil return connect_networks(pos, positions)
for tblname,table in pairs(network) do end
if tblname ~= "tier" then
for machinenum,machine in pairs(table) do -- Actually add it to the (cached) network
if machine.x == pos.x -- This is similar to check_node_subp
and machine.y == pos.y local pos_hash = minetest.hash_node_position(pos)
and machine.z == pos.z then technic.cables[pos_hash] = network_id
table[machinenum] = nil pos.visited = 1
end if technic.is_tier_cable(name, tier) then
end network.all_nodes[pos_hash] = pos
end elseif technic.machines[tier][node.name] then
if technic.machines[tier][node.name] == technic.producer then
table.insert(network.PR_nodes,pos)
elseif technic.machines[tier][node.name] == technic.receiver then
table.insert(network.RE_nodes,pos)
elseif technic.machines[tier][node.name] == technic.producer_receiver then
table.insert(network.PR_nodes,pos)
table.insert(network.RE_nodes,pos)
elseif technic.machines[tier][node.name] == technic.battery then
table.insert(network.BA_nodes,pos)
end
end
end
local function remove_network_node(pos)
-- Get the network
local network_id = technic.pos2network(pos)
if not network_id then
-- We're evidently not on a network, nothing to add ourselves to
return
end
local positions = check_connections(pos)
if #positions < 1 then return end
local dead_end = #positions == 1
if not dead_end then
-- TODO: Check branches around and switching stations for branches:
-- remove branches that do not have switching station.
-- remove branches not connected to another branch.
-- do not rebuild networks here, leave that for ABM to reduce unnecessary cache building.
-- For now remove network like how it was done before:
technic.remove_network(network_id)
return
end
-- Dead end removed, remove it from the network
local network = technic.networks[network_id]
technic.cables[minetest.hash_node_position(pos)] = nil
-- TODO: Looping over all keys in network is not right way to do this, should fix to use known machine types.
-- Better to add network function that knows what to remove, something like technic.remove_node(network_id, pos)
for tblname,table in pairs(network) do
if type(table) == "table" then
for machinenum,machine in pairs(table) do
if machine.x == pos.x
and machine.y == pos.y
and machine.z == pos.z then
table[machinenum] = nil
end end
else
-- Not a dead end, so the whole network needs to be recalculated
for _,v in pairs(technic.networks[net].all_nodes) do
local pos1 = minetest.hash_node_position(v)
technic.cables[pos1] = nil
end
technic.networks[net] = nil
end end
end end
end end
@ -142,7 +158,8 @@ function technic.register_cable(tier, size, description, prefix, override_cable,
prefix = prefix or "" prefix = prefix or ""
override_cable_plate = override_cable_plate or override_cable override_cable_plate = override_cable_plate or override_cable
local ltier = string.lower(tier) local ltier = string.lower(tier)
cable_tier["technic:"..ltier..prefix.."_cable"] = tier local node_name = "technic:"..ltier..prefix.."_cable"
cable_tier[node_name] = tier
local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
["technic_"..ltier.."_cable"] = 1} ["technic_"..ltier.."_cable"] = 1}
@ -158,22 +175,22 @@ function technic.register_cable(tier, size, description, prefix, override_cable,
connect_right = {-size, -size, -size, 0.5, size, size}, -- x+ connect_right = {-size, -size, -size, 0.5, size, size}, -- x+
} }
minetest.register_node("technic:"..ltier..prefix.."_cable", override_table({ minetest.register_node(node_name, override_table({
description = S("%s Cable"):format(tier), description = S("%s Cable"):format(tier),
tiles = {"technic_"..ltier..prefix.."_cable.png"}, tiles = {"technic_"..ltier..prefix.."_cable.png"},
inventory_image = "technic_"..ltier..prefix.."_cable_wield.png", inventory_image = "technic_"..ltier..prefix.."_cable_wield.png",
wield_image = "technic_"..ltier..prefix.."_cable_wield.png", wield_image = "technic_"..ltier..prefix.."_cable_wield.png",
groups = groups, groups = groups,
sounds = default.node_sound_wood_defaults(), sounds = default.node_sound_wood_defaults(),
drop = "technic:"..ltier..prefix.."_cable", drop = node_name,
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
drawtype = "nodebox", drawtype = "nodebox",
node_box = node_box, node_box = node_box,
connects_to = {"group:technic_"..ltier.."_cable", connects_to = {"group:technic_"..ltier.."_cable",
"group:technic_"..ltier, "group:technic_all_tiers"}, "group:technic_"..ltier, "group:technic_all_tiers"},
on_construct = clear_networks, on_construct = function(pos) place_network_node(pos, node_name) end,
on_destruct = clear_networks, on_destruct = remove_network_node,
}, override_cable)) }, override_cable))
local xyz = { local xyz = {
@ -205,15 +222,15 @@ function technic.register_cable(tier, size, description, prefix, override_cable,
tiles = {"technic_"..ltier..prefix.."_cable.png"}, tiles = {"technic_"..ltier..prefix.."_cable.png"},
groups = table.copy(groups), groups = table.copy(groups),
sounds = default.node_sound_wood_defaults(), sounds = default.node_sound_wood_defaults(),
drop = "technic:"..ltier..prefix.."_cable_plate_1", drop = node_name .. "_plate_1",
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
drawtype = "nodebox", drawtype = "nodebox",
node_box = table.copy(node_box), node_box = table.copy(node_box),
connects_to = {"group:technic_"..ltier.."_cable", connects_to = {"group:technic_"..ltier.."_cable",
"group:technic_"..ltier, "group:technic_all_tiers"}, "group:technic_"..ltier, "group:technic_all_tiers"},
on_construct = clear_networks, on_construct = function(pos) place_network_node(pos, node_name.."_plate_"..i) end,
on_destruct = clear_networks, on_destruct = remove_network_node,
} }
def.node_box.fixed = { def.node_box.fixed = {
{-size, -size, -size, size, size, size}, {-size, -size, -size, size, size, size},
@ -254,7 +271,7 @@ function technic.register_cable(tier, size, description, prefix, override_cable,
if num == nil then num = 1 end if num == nil then num = 1 end
return item_place_override_node( return item_place_override_node(
itemstack, placer, pointed_thing, itemstack, placer, pointed_thing,
{name = "technic:"..ltier..prefix.."_cable_plate_"..num} {name = node_name.."_plate_"..num}
) )
end end
else else
@ -271,39 +288,41 @@ function technic.register_cable(tier, size, description, prefix, override_cable,
num = num + dir num = num + dir
num = (num >= 1 and num) or num + 6 num = (num >= 1 and num) or num + 6
num = (num <= 6 and num) or num - 6 num = (num <= 6 and num) or num - 6
minetest.swap_node(pos, {name = "technic:"..ltier..prefix.."_cable_plate_"..num}) minetest.swap_node(pos, {name = node_name.."_plate_"..num})
end end
minetest.register_node("technic:"..ltier..prefix.."_cable_plate_"..i, override_table(def, override_cable_plate)) minetest.register_node(node_name.."_plate_"..i, override_table(def, override_cable_plate))
cable_tier["technic:"..ltier..prefix.."_cable_plate_"..i] = tier cable_tier[node_name.."_plate_"..i] = tier
end end
local c = "technic:"..ltier..prefix.."_cable"
minetest.register_craft({ minetest.register_craft({
output = "technic:"..ltier..prefix.."_cable_plate_1 5", output = node_name.."_plate_1 5",
recipe = { recipe = {
{"", "", c}, {"" , "" , node_name},
{c , c , c}, {node_name, node_name, node_name},
{"", "", c}, {"" , "" , node_name},
} }
}) })
minetest.register_craft({ minetest.register_craft({
output = c, output = node_name,
recipe = { recipe = {
{"technic:"..ltier..prefix.."_cable_plate_1"}, {node_name.."_plate_1"},
} }
}) })
end end
minetest.register_on_placenode(function(pos, node)
local function clear_nets_if_machine(pos, node)
for tier, machine_list in pairs(technic.machines) do for tier, machine_list in pairs(technic.machines) do
if machine_list[node.name] ~= nil then if machine_list[node.name] ~= nil then
return clear_networks(pos) return place_network_node(pos, node)
end end
end end
end end)
minetest.register_on_placenode(clear_nets_if_machine)
minetest.register_on_dignode(clear_nets_if_machine)
minetest.register_on_dignode(function(pos, node)
for tier, machine_list in pairs(technic.machines) do
if machine_list[node.name] ~= nil then
return remove_network_node(pos)
end
end
end)

View File

@ -92,11 +92,19 @@ minetest.register_node("technic:switching_station",{
if channel ~= meta:get_string("channel") then if channel ~= meta:get_string("channel") then
return return
end end
digilines.receptor_send(pos, technic.digilines.rules, channel, { local network_id = technic.sw_pos2network(pos)
supply = meta:get_int("supply"), local network = network_id and technic.networks[network_id]
demand = meta:get_int("demand"), if network then
lag = meta:get_int("lag") digilines.receptor_send(pos, technic.digilines.rules, channel, {
}) supply = network.supply,
demand = network.demand,
lag = network.lag
})
else
digilines.receptor_send(pos, technic.digilines.rules, channel, {
error = "No network",
})
end
end end
}, },
}, },
@ -106,14 +114,6 @@ minetest.register_node("technic:switching_station",{
-- The action code for the switching station -- -- The action code for the switching station --
----------------------------------------------- -----------------------------------------------
function technic.switching_station_run(pos)
local network_id = technic.sw_pos2network(pos)
if network_id then
return technic.network_run(network_id)
end
--print(string.format("technic.switching_station_run(%s) failed, no network available", minetest.pos_to_string(pos)))
end
-- Timeout ABM -- Timeout ABM
-- Timeout for a node in case it was disconnected from the network -- Timeout for a node in case it was disconnected from the network
-- A node must be touched by the station continuously in order to function -- A node must be touched by the station continuously in order to function
@ -168,9 +168,6 @@ minetest.register_abm({
local remaining = technic.reset_overloaded(network_id) local remaining = technic.reset_overloaded(network_id)
if remaining > 0 then if remaining > 0 then
infotext = S("%s Network Overloaded, Restart in %dms"):format(S("Switching Station"), remaining / 1000) infotext = S("%s Network Overloaded, Restart in %dms"):format(S("Switching Station"), remaining / 1000)
-- Set switching station supply value to zero to clean up power monitor supply info
-- TODO: This should be saved with network and removed from metadata
meta:set_int("supply",0)
else else
infotext = S("%s Restarting Network"):format(S("Switching Station")) infotext = S("%s Restarting Network"):format(S("Switching Station"))
end end
@ -187,8 +184,3 @@ minetest.register_abm({
end end
end, end,
}) })
for tier, machines in pairs(technic.machines) do
-- SPECIAL will not be traversed
technic.register_machine(tier, "technic:switching_station", "SPECIAL")
end

View File

@ -86,12 +86,13 @@ minetest.register_globalstep(function(dtime)
for network_id, switch in pairs(switches) do for network_id, switch in pairs(switches) do
local pos = technic.network2sw_pos(network_id) local pos = technic.network2sw_pos(network_id)
local network = technic.networks[network_id]
local diff = now - switch.time local diff = now - switch.time
minetest.get_voxel_manip(pos, pos) minetest.get_voxel_manip(pos, pos)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
if node.name ~= "technic:switching_station" then if network == nil or node.name ~= "technic:switching_station" then
-- station vanished -- station vanished
switches[network_id] = nil switches[network_id] = nil
@ -102,13 +103,11 @@ minetest.register_globalstep(function(dtime)
if switch.skip < 1 then if switch.skip < 1 then
local start = minetest.get_us_time() local start = minetest.get_us_time()
technic.switching_station_run(pos) technic.network_run(network_id)
local switch_diff = minetest.get_us_time() - start local switch_diff = minetest.get_us_time() - start
local meta = minetest.get_meta(pos)
-- set lag in microseconds into the "lag" meta field -- set lag in microseconds into the "lag" meta field
meta:set_int("lag", switch_diff) network.lag = switch_diff
-- overload detection -- overload detection
if switch_diff > 250000 then if switch_diff > 250000 then

View File

@ -1,6 +1,13 @@
local function noop(...) end local function noop(...) end
local function dummy_coords(...) return { x = 123, y = 123, z = 123 } end local function dummy_coords(...) return { x = 123, y = 123, z = 123 } end
_G.world = { nodes = {} }
local world = _G.world
_G.world.set_node = function(pos, node)
local hash = minetest.hash_node_position(pos)
world.nodes[hash] = node
end
_G.core = {} _G.core = {}
_G.minetest = _G.core _G.minetest = _G.core
@ -64,12 +71,26 @@ _G.minetest.register_lbm = noop
_G.minetest.register_abm = noop _G.minetest.register_abm = noop
_G.minetest.register_chatcommand = noop _G.minetest.register_chatcommand = noop
_G.minetest.chat_send_player = noop _G.minetest.chat_send_player = noop
_G.minetest.register_alias = noop
_G.minetest.register_craftitem = noop _G.minetest.register_craftitem = noop
_G.minetest.register_craft = noop _G.minetest.register_craft = noop
_G.minetest.register_node = noop
_G.minetest.register_on_placenode = noop _G.minetest.register_on_placenode = noop
_G.minetest.register_on_dignode = noop _G.minetest.register_on_dignode = noop
_G.minetest.item_drop = noop _G.minetest.item_drop = noop
_G.minetest.get_node = function(pos)
local hash = minetest.hash_node_position(pos)
return world.nodes[hash] or {name="IGNORE",param2=0}
end
_G.minetest.get_modpath = function(...) return "./unit_test_modpath" end _G.minetest.get_modpath = function(...) return "./unit_test_modpath" end
_G.minetest.get_pointed_thing_position = dummy_coords _G.minetest.get_pointed_thing_position = dummy_coords
--
-- Minetest default noop table
--
local default = { __index = function(...) return function(...)end end }
_G.default = {}
setmetatable(_G.default, default)

View File

@ -1,5 +1,37 @@
local world = {
{{x=100,y=100,z=100}, "technic:lv_cable"},
{{x=101,y=100,z=100}, "technic:lv_cable"},
{{x=102,y=100,z=100}, "technic:lv_cable"},
{{x=103,y=100,z=100}, "technic:lv_cable"},
{{x=100,y=101,z=100}, "technic:switching_station"},
{{x=100,y=200,z=100}, "technic:mv_cable"},
{{x=101,y=200,z=100}, "technic:mv_cable"},
{{x=102,y=200,z=100}, "technic:mv_cable"},
{{x=103,y=200,z=100}, "technic:mv_cable"},
{{x=100,y=201,z=100}, "technic:switching_station"},
{{x=100,y=300,z=100}, "technic:hv_cable"},
{{x=101,y=300,z=100}, "technic:hv_cable"},
{{x=102,y=300,z=100}, "technic:hv_cable"},
{{x=103,y=300,z=100}, "technic:hv_cable"},
{{x=100,y=301,z=100}, "technic:switching_station"},
}
-- Build world for tests
for _,node in ipairs(world) do
_G.world.set_node(node[1], {name=node[2], param2=0})
end
_G.technic = {} _G.technic = {}
_G.technic.S = string.format _G.technic.S = string.format
_G.technic.getter = function(...) return "" end
sourcefile("register") sourcefile("register")
sourcefile("machines/register/cables")
sourcefile("machines/LV/cables")
sourcefile("machines/MV/cables")
sourcefile("machines/HV/cables")

View File

@ -37,6 +37,17 @@ describe("Power network helper", function()
assert.same(net_id, technic.sw_pos2network(sw_pos) ) assert.same(net_id, technic.sw_pos2network(sw_pos) )
end) end)
it("returns nil tier for empty position", function()
assert.is_nil(technic.sw_pos2tier({x=9999,y=9999,z=9999}))
end)
it("returns correct tier for switching station position", function()
-- World is defined in fixtures/network.lua
assert.same("LV", technic.sw_pos2tier({x=100,y=101,z=100}))
assert.same("MV", technic.sw_pos2tier({x=100,y=201,z=100}))
assert.same("HV", technic.sw_pos2tier({x=100,y=301,z=100}))
end)
end) end)
--[[ TODO: --[[ TODO: