power distribution changed
This commit is contained in:
parent
857def71e8
commit
c088867c00
@ -8,8 +8,7 @@ local PWR_PERF = 10
|
|||||||
local PWR_CAPA = 300
|
local PWR_CAPA = 300
|
||||||
|
|
||||||
local Cable = techage.ElectricCable
|
local Cable = techage.ElectricCable
|
||||||
local secondary_power = techage.power.secondary_power
|
local power = techage.power
|
||||||
local power_switched = techage.power.power_switched
|
|
||||||
|
|
||||||
local function in_range(val, min, max)
|
local function in_range(val, min, max)
|
||||||
if val < min then return min end
|
if val < min then return min end
|
||||||
@ -32,52 +31,36 @@ end
|
|||||||
local function node_timer(pos, elapsed)
|
local function node_timer(pos, elapsed)
|
||||||
--print("node_timer akku "..S(pos))
|
--print("node_timer akku "..S(pos))
|
||||||
local mem = tubelib2.get_mem(pos)
|
local mem = tubelib2.get_mem(pos)
|
||||||
mem.capa = mem.capa or 0
|
if mem.running then
|
||||||
if mem.generating then
|
mem.delivered = power.secondary_alive(pos, mem, mem.capa, PWR_CAPA)
|
||||||
local delivered
|
--print("provided", mem.delivered)
|
||||||
if mem.capa >= PWR_CAPA then
|
|
||||||
delivered = secondary_power(pos, PWR_PERF, 0)
|
|
||||||
elseif mem.capa <= 0 then
|
|
||||||
delivered = secondary_power(pos, 0, PWR_PERF)
|
|
||||||
else
|
|
||||||
delivered = secondary_power(pos, PWR_PERF, PWR_PERF)
|
|
||||||
end
|
|
||||||
if delivered ~= mem.delivered then
|
|
||||||
mem.delivered = delivered
|
|
||||||
--techage.power2.power_switched(pos)
|
|
||||||
end
|
|
||||||
mem.capa = mem.capa - mem.delivered
|
mem.capa = mem.capa - mem.delivered
|
||||||
mem.capa = in_range(mem.capa, 0, PWR_CAPA)
|
mem.capa = in_range(mem.capa, 0, PWR_CAPA)
|
||||||
--print("delivered = "..mem.delivered)
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
mem.delivered = 0
|
return mem.running
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function on_receive_fields(pos, formname, fields, player)
|
local function on_receive_fields(pos, formname, fields, player)
|
||||||
if minetest.is_protected(pos, player:get_player_name()) then
|
if minetest.is_protected(pos, player:get_player_name()) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local mem = tubelib2.get_mem(pos)
|
||||||
|
techage.power.network_changed(pos, mem)
|
||||||
|
|
||||||
if fields.update then
|
if fields.update then
|
||||||
local mem = tubelib2.get_mem(pos)
|
|
||||||
M(pos):set_string("formspec", formspec(pos, mem))
|
M(pos):set_string("formspec", formspec(pos, mem))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function on_rightclick(pos)
|
|
||||||
local mem = tubelib2.get_mem(pos)
|
|
||||||
M(pos):set_string("formspec", formspec(pos, mem))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function after_place_node(pos, placer)
|
local function after_place_node(pos, placer)
|
||||||
local mem = tubelib2.get_mem(pos)
|
local mem = tubelib2.get_mem(pos)
|
||||||
mem.generating = true
|
mem.running = true
|
||||||
mem.capa = 0
|
mem.capa = 0
|
||||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||||
techage.power.power_switched(pos)
|
power.secondary_start(pos, mem, PWR_PERF, PWR_PERF)
|
||||||
on_rightclick(pos)
|
M(pos):set_string("formspec", formspec(pos, mem))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -97,7 +80,6 @@ minetest.register_node("techage:akku", {
|
|||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
after_place_node = after_place_node,
|
after_place_node = after_place_node,
|
||||||
on_receive_fields = on_receive_fields,
|
on_receive_fields = on_receive_fields,
|
||||||
on_rightclick = on_rightclick,
|
|
||||||
on_timer = node_timer,
|
on_timer = node_timer,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ local PWR_NEEDED = 5
|
|||||||
local CYCLE_TIME = 4
|
local CYCLE_TIME = 4
|
||||||
|
|
||||||
local Cable = techage.ElectricCable
|
local Cable = techage.ElectricCable
|
||||||
local consume_power = techage.power.consume_power
|
local power = techage.power
|
||||||
|
|
||||||
local function swap_node(pos, name)
|
local function swap_node(pos, name)
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
@ -18,45 +18,42 @@ local function swap_node(pos, name)
|
|||||||
minetest.swap_node(pos, node)
|
minetest.swap_node(pos, node)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function on_power(pos, mem)
|
||||||
local function on_power(pos)
|
print("on_power")
|
||||||
local mem = tubelib2.get_mem(pos)
|
if mem.running then
|
||||||
--print("sink on_power", mem.running)
|
swap_node(pos, "techage:sink_on")
|
||||||
mem.timer_running = (mem.timer_running or 1) - 1
|
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||||
if mem.running and mem.timer_running >= 0 then
|
M(pos):set_string("infotext", "on")
|
||||||
local got = consume_power(pos, PWR_NEEDED)
|
|
||||||
if got < PWR_NEEDED then
|
|
||||||
swap_node(pos, "techage:sink")
|
|
||||||
else
|
|
||||||
swap_node(pos, "techage:sink_on")
|
|
||||||
mem.power_available = true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function on_nopower(pos, mem)
|
||||||
|
print("on_nopower")
|
||||||
|
swap_node(pos, "techage:sink")
|
||||||
|
M(pos):set_string("infotext", "nopower")
|
||||||
|
end
|
||||||
|
|
||||||
local function node_timer(pos, elapsed)
|
local function node_timer(pos, elapsed)
|
||||||
--print("node_timer sink "..S(pos))
|
--print("node_timer sink "..S(pos))
|
||||||
local mem = tubelib2.get_mem(pos)
|
local mem = tubelib2.get_mem(pos)
|
||||||
if mem.running and not mem.power_available then
|
power.consumer_alive(pos, mem)
|
||||||
--print("sink not triggered")
|
return mem.running
|
||||||
swap_node(pos, "techage:sink")
|
|
||||||
end
|
|
||||||
mem.power_available = false
|
|
||||||
mem.timer_running = CYCLE_TIME/2 + 1
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function on_rightclick(pos, node, clicker)
|
local function on_rightclick(pos, node, clicker)
|
||||||
local mem = tubelib2.get_mem(pos)
|
local mem = tubelib2.get_mem(pos)
|
||||||
if not mem.running then
|
if not mem.running and power.power_available(pos, mem, PWR_NEEDED) then
|
||||||
mem.running = true
|
mem.running = true
|
||||||
node_timer(pos, 2)
|
swap_node(pos, "techage:sink_on")
|
||||||
|
power.consumer_start(pos, mem, CYCLE_TIME, PWR_NEEDED)
|
||||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||||
|
M(pos):set_string("infotext", "on")
|
||||||
else
|
else
|
||||||
swap_node(pos, "techage:sink")
|
|
||||||
minetest.get_node_timer(pos):stop()
|
|
||||||
mem.running = false
|
mem.running = false
|
||||||
|
swap_node(pos, "techage:sink")
|
||||||
|
power.consumer_stop(pos, mem)
|
||||||
|
minetest.get_node_timer(pos):stop()
|
||||||
|
M(pos):set_string("infotext", "off")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -64,6 +61,11 @@ end
|
|||||||
minetest.register_node("techage:sink", {
|
minetest.register_node("techage:sink", {
|
||||||
description = "Sink",
|
description = "Sink",
|
||||||
tiles = {'techage_electric_button.png'},
|
tiles = {'techage_electric_button.png'},
|
||||||
|
|
||||||
|
after_place_node = function(pos)
|
||||||
|
M(pos):set_string("infotext", "off")
|
||||||
|
end,
|
||||||
|
|
||||||
on_timer = node_timer,
|
on_timer = node_timer,
|
||||||
on_rightclick = on_rightclick,
|
on_rightclick = on_rightclick,
|
||||||
|
|
||||||
@ -96,4 +98,5 @@ minetest.register_node("techage:sink_on", {
|
|||||||
techage.power.register_node({"techage:sink", "techage:sink_on"}, {
|
techage.power.register_node({"techage:sink", "techage:sink_on"}, {
|
||||||
power_network = Cable,
|
power_network = Cable,
|
||||||
on_power = on_power,
|
on_power = on_power,
|
||||||
|
on_nopower = on_nopower,
|
||||||
})
|
})
|
||||||
|
@ -7,32 +7,33 @@ local CYCLE_TIME = 2
|
|||||||
local PWR_CAPA = 15
|
local PWR_CAPA = 15
|
||||||
|
|
||||||
local Cable = techage.ElectricCable
|
local Cable = techage.ElectricCable
|
||||||
local provide_power = techage.power.provide_power
|
local power = techage.power
|
||||||
|
|
||||||
local function node_timer(pos, elapsed)
|
local function node_timer(pos, elapsed)
|
||||||
--print("node_timer source "..S(pos))
|
--print("node_timer source "..S(pos))
|
||||||
local mem = tubelib2.get_mem(pos)
|
local mem = tubelib2.get_mem(pos)
|
||||||
if mem.generating then
|
if mem.generating then
|
||||||
local provided = provide_power(pos, PWR_CAPA)
|
local provided = power.generator_alive(pos, mem)
|
||||||
return true
|
--print("provided", provided)
|
||||||
end
|
end
|
||||||
return false
|
return mem.generating
|
||||||
end
|
end
|
||||||
|
|
||||||
local function on_rightclick(pos, node, clicker)
|
local function on_rightclick(pos, node, clicker)
|
||||||
local mem = tubelib2.get_mem(pos)
|
local mem = tubelib2.get_mem(pos)
|
||||||
if not mem.generating then
|
if not mem.generating then
|
||||||
mem.generating = true
|
mem.generating = true
|
||||||
node_timer(pos, 2)
|
power.generator_start(pos, mem, PWR_CAPA)
|
||||||
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
minetest.get_node_timer(pos):start(CYCLE_TIME)
|
||||||
|
M(pos):set_string("infotext", "on")
|
||||||
else
|
else
|
||||||
minetest.get_node_timer(pos):stop()
|
|
||||||
mem.generating = false
|
mem.generating = false
|
||||||
|
power.generator_stop(pos, mem)
|
||||||
|
minetest.get_node_timer(pos):stop()
|
||||||
|
M(pos):set_string("infotext", "off")
|
||||||
end
|
end
|
||||||
techage.power.power_switched(pos)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
minetest.register_node("techage:source", {
|
minetest.register_node("techage:source", {
|
||||||
description = "Source",
|
description = "Source",
|
||||||
tiles = {
|
tiles = {
|
||||||
@ -44,6 +45,10 @@ minetest.register_node("techage:source", {
|
|||||||
'techage_electric_button.png^techage_appl_electronic_fab.png',
|
'techage_electric_button.png^techage_appl_electronic_fab.png',
|
||||||
'techage_electric_button.png^techage_appl_electronic_fab.png',
|
'techage_electric_button.png^techage_appl_electronic_fab.png',
|
||||||
},
|
},
|
||||||
|
after_place_node = function(pos)
|
||||||
|
M(pos):set_string("infotext", "off")
|
||||||
|
end,
|
||||||
|
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
groups = {cracky=2, crumbly=2, choppy=2},
|
groups = {cracky=2, crumbly=2, choppy=2},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
|
@ -84,7 +84,7 @@ local function node_timer(pos, elapsed)
|
|||||||
State:keep_running(pos, mem, COUNTDOWN_TICKS)
|
State:keep_running(pos, mem, COUNTDOWN_TICKS)
|
||||||
mem.power_available = (mem.power_available or 1) - 1
|
mem.power_available = (mem.power_available or 1) - 1
|
||||||
mem.triggered = (mem.triggered or 1) - 1
|
mem.triggered = (mem.triggered or 1) - 1
|
||||||
if mem.power_available <= 0 or mem.triggered <= 0 then
|
if mem.power_available < 0 or mem.triggered < 0 then
|
||||||
power_switched(pos)
|
power_switched(pos)
|
||||||
State:stop(pos, mem)
|
State:stop(pos, mem)
|
||||||
mem.generating = false
|
mem.generating = false
|
||||||
|
1
init.lua
1
init.lua
@ -43,6 +43,7 @@ else
|
|||||||
|
|
||||||
-- Power networks
|
-- Power networks
|
||||||
dofile(MP.."/power/power.lua")
|
dofile(MP.."/power/power.lua")
|
||||||
|
dofile(MP.."/power/power2.lua")
|
||||||
dofile(MP.."/power/junction.lua")
|
dofile(MP.."/power/junction.lua")
|
||||||
dofile(MP.."/power/drive_axle.lua")
|
dofile(MP.."/power/drive_axle.lua")
|
||||||
dofile(MP.."/power/steam_pipe.lua")
|
dofile(MP.."/power/steam_pipe.lua")
|
||||||
|
@ -171,6 +171,7 @@ minetest.register_node("techage:charcoal_burn", {
|
|||||||
return false
|
return false
|
||||||
end,
|
end,
|
||||||
drop = "",
|
drop = "",
|
||||||
|
paramtype = "light",
|
||||||
light_source = 10,
|
light_source = 10,
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
groups = {crumbly = 2, falling_node = 1, not_in_creative_inventory=1},
|
groups = {crumbly = 2, falling_node = 1, not_in_creative_inventory=1},
|
||||||
|
@ -17,8 +17,7 @@ local M = minetest.get_meta
|
|||||||
local S = techage.S
|
local S = techage.S
|
||||||
|
|
||||||
local Cable = techage.ElectricCable
|
local Cable = techage.ElectricCable
|
||||||
local power_switched = techage.power.power_switched
|
local power = techage.power
|
||||||
local power_available = techage.power.power_available
|
|
||||||
|
|
||||||
local size = 3/32
|
local size = 3/32
|
||||||
local Boxes = {
|
local Boxes = {
|
||||||
@ -40,10 +39,10 @@ techage.register_junction("techage:electric_junction", 2/8, Boxes, Cable, {
|
|||||||
after_tube_update = function(node, pos, out_dir, peer_pos, peer_in_dir)
|
after_tube_update = function(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||||
local name = "techage:electric_junction"..techage.junction_type(pos, Cable)
|
local name = "techage:electric_junction"..techage.junction_type(pos, Cable)
|
||||||
minetest.swap_node(pos, {name = name, param2 = 0})
|
minetest.swap_node(pos, {name = name, param2 = 0})
|
||||||
power_switched(pos)
|
power.network_changed(pos, tubelib2.get_mem(pos))
|
||||||
end,
|
end,
|
||||||
is_power_available = function(pos)
|
is_power_available = function(pos)
|
||||||
return techage.power.power_accounting(pos)
|
return techage.power.power_accounting(pos, tubelib2.get_mem(pos))
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
640
power/power.lua
640
power/power.lua
@ -19,16 +19,17 @@ local P = minetest.string_to_pos
|
|||||||
local M = minetest.get_meta
|
local M = minetest.get_meta
|
||||||
-- Techage Related Data
|
-- Techage Related Data
|
||||||
local PWR = function(pos) return (minetest.registered_nodes[minetest.get_node(pos).name] or {}).power end
|
local PWR = function(pos) return (minetest.registered_nodes[minetest.get_node(pos).name] or {}).power end
|
||||||
local PWRN = function(node) return (minetest.registered_nodes[node.name] or {}).power end
|
|
||||||
|
|
||||||
-- Used to determine the already passed nodes while power distribution
|
-- Used to determine the already passed nodes while power distribution
|
||||||
local Route = {}
|
local Route = {}
|
||||||
|
|
||||||
local function in_range(val, min, max)
|
techage.power = {}
|
||||||
if val < min then return min end
|
|
||||||
if val > max then return max end
|
-- Consumer States
|
||||||
return val
|
local STOPPED = 1
|
||||||
end
|
local NOPOWER = 2
|
||||||
|
local RUNNING = 3
|
||||||
|
|
||||||
|
|
||||||
local function pos_already_reached(pos)
|
local function pos_already_reached(pos)
|
||||||
local key = minetest.hash_node_position(pos)
|
local key = minetest.hash_node_position(pos)
|
||||||
@ -39,88 +40,21 @@ local function pos_already_reached(pos)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local SideToDir = {B=1, R=2, F=3, L=4, D=5, U=6}
|
|
||||||
|
|
||||||
local function side_to_dir(param2, side)
|
|
||||||
local dir = SideToDir[side]
|
|
||||||
if dir < 5 then
|
|
||||||
dir = (((dir - 1) + (param2 % 4)) % 4) + 1
|
|
||||||
end
|
|
||||||
return dir
|
|
||||||
end
|
|
||||||
|
|
||||||
function techage.get_pos(pos, side)
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
local dir = nil
|
|
||||||
if node.name ~= "air" and node.name ~= "ignore" then
|
|
||||||
dir = side_to_dir(node.param2, side)
|
|
||||||
end
|
|
||||||
return tubelib2.get_pos(pos, dir)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function set_conn_dirs(pos, sides)
|
|
||||||
local tbl = {}
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
if type(sides) == "function" then
|
|
||||||
tbl = sides(pos, node)
|
|
||||||
else
|
|
||||||
for _,side in ipairs(sides) do
|
|
||||||
tbl[#tbl+1] = tubelib2.Turn180Deg[side_to_dir(node.param2, side)]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
M(pos):set_string("power_dirs", minetest.serialize(tbl))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function valid_indir(pos, in_dir)
|
|
||||||
local s = M(pos):get_string("power_dirs")
|
|
||||||
if s == "" then
|
|
||||||
local pwr = PWR(pos)
|
|
||||||
if pwr then
|
|
||||||
set_conn_dirs(pos, pwr.conn_sides)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if s ~= "" then
|
|
||||||
for _,dir in ipairs(minetest.deserialize(s)) do
|
|
||||||
if dir == in_dir then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function valid_outdir(pos, out_dir)
|
|
||||||
return valid_indir(pos, tubelib2.Turn180Deg[out_dir])
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Both nodes are from the same power network type?
|
|
||||||
local function matching_nodes(pos, peer_pos)
|
|
||||||
local tube_type1 = pos and PWR(pos) and PWR(pos).power_network.tube_type
|
|
||||||
local tube_type2 = peer_pos and PWR(peer_pos) and PWR(peer_pos).power_network.tube_type
|
|
||||||
return not tube_type1 or not tube_type2 or tube_type1 == tube_type2
|
|
||||||
end
|
|
||||||
|
|
||||||
local function min(val, max)
|
local function min(val, max)
|
||||||
if val < 0 then return 0 end
|
if val < 0 then return 0 end
|
||||||
if val > max then return max end
|
if val > max then return max end
|
||||||
return val
|
return val
|
||||||
end
|
end
|
||||||
|
|
||||||
-- called from master every cycle (2 seconds)
|
local function accounting(pos, mem)
|
||||||
local function accounting(mem)
|
|
||||||
-- defensive programming
|
|
||||||
mem.needed1 = mem.needed1 or 0
|
|
||||||
mem.needed2 = mem.needed2 or 0
|
|
||||||
mem.available1 = mem.available1 or 0
|
|
||||||
mem.available2 = mem.available2 or 0
|
|
||||||
-- calculate the primary and secondary supply and demand
|
-- calculate the primary and secondary supply and demand
|
||||||
mem.supply1 = min(mem.needed1 + mem.needed2, mem.available1)
|
mem.mst_supply1 = min(mem.mst_needed1 + mem.mst_needed2, mem.mst_available1)
|
||||||
mem.demand1 = min(mem.needed1, mem.available1 + mem.available2)
|
mem.mst_demand1 = min(mem.mst_needed1, mem.mst_available1 + mem.mst_available2)
|
||||||
mem.supply2 = min(mem.demand1 - mem.supply1, mem.available2)
|
mem.mst_supply2 = min(mem.mst_demand1 - mem.mst_supply1, mem.mst_available2)
|
||||||
mem.demand2 = min(mem.supply1 - mem.demand1, mem.available1)
|
mem.mst_demand2 = min(mem.mst_supply1 - mem.mst_demand1, mem.mst_available1)
|
||||||
mem.reserve = (mem.available1 + mem.available2) > mem.needed1
|
mem.mst_reserve = (mem.mst_available1 + mem.mst_available2) - mem.mst_needed1
|
||||||
--print("needed = "..mem.needed1.."/"..mem.needed2..", available = "..mem.available1.."/"..mem.available2)
|
--print("needed = "..mem.mst_needed1.."/"..mem.mst_needed2..", available = "..mem.mst_available1.."/"..mem.mst_available2)
|
||||||
--print("supply = "..mem.supply1.."/"..mem.supply2..", demand = "..mem.demand1.."/"..mem.demand2..", reserve = "..dump(mem.reserve))
|
--print("supply = "..mem.mst_supply1.."/"..mem.mst_supply2..", demand = "..mem.mst_demand1.."/"..mem.mst_demand2..", reserve = "..mem.mst_reserve)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function connection_walk(pos, clbk)
|
local function connection_walk(pos, clbk)
|
||||||
@ -137,6 +71,24 @@ local function connection_walk(pos, clbk)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function consumer_turn_off(pos, mem)
|
||||||
|
local pwr = PWR(pos)
|
||||||
|
print("consumer_turn_off")
|
||||||
|
if pwr and pwr.on_nopower then
|
||||||
|
pwr.on_nopower(pos, mem)
|
||||||
|
end
|
||||||
|
mem.pwr_node_alive_cnt = 0
|
||||||
|
mem.pwr_state = NOPOWER
|
||||||
|
end
|
||||||
|
|
||||||
|
local function consumer_turn_on(pos, mem)
|
||||||
|
local pwr = PWR(pos)
|
||||||
|
print("consumer_turn_on")
|
||||||
|
if pwr and pwr.on_power then
|
||||||
|
pwr.on_power(pos, mem)
|
||||||
|
end
|
||||||
|
mem.pwr_state = RUNNING
|
||||||
|
end
|
||||||
|
|
||||||
-- determine one "generating" node as master (largest hash number)
|
-- determine one "generating" node as master (largest hash number)
|
||||||
local function determine_master(pos)
|
local function determine_master(pos)
|
||||||
@ -145,15 +97,17 @@ local function determine_master(pos)
|
|||||||
local hash = 0
|
local hash = 0
|
||||||
local master = nil
|
local master = nil
|
||||||
connection_walk(pos, function(pos, mem)
|
connection_walk(pos, function(pos, mem)
|
||||||
mem.generator_available = (mem.generator_available or 1) - 1
|
if (mem.pwr_node_alive_cnt or 0) >= 0 and
|
||||||
if mem.generating and mem.generator_available > 0 then
|
(mem.pwr_available or 0) > 0 or
|
||||||
local new = minetest.hash_node_position(pos)
|
(mem.pwr_available2 or 0) > 0 then -- active generator?
|
||||||
if hash <= new then
|
|
||||||
hash = new
|
local new = minetest.hash_node_position(pos)
|
||||||
master = pos
|
if hash <= new then
|
||||||
end
|
hash = new
|
||||||
|
master = pos
|
||||||
end
|
end
|
||||||
end)
|
end
|
||||||
|
end)
|
||||||
return master
|
return master
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -162,302 +116,256 @@ local function store_master(pos, master_pos)
|
|||||||
Route = {}
|
Route = {}
|
||||||
pos_already_reached(pos)
|
pos_already_reached(pos)
|
||||||
connection_walk(pos, function(pos, mem)
|
connection_walk(pos, function(pos, mem)
|
||||||
mem.master_pos = master_pos
|
mem.pwr_master_pos = master_pos
|
||||||
mem.is_master = false
|
mem.pwr_is_master = false
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function trigger_nodes(pos)
|
local function handle_generator(mst_mem, mem, pos, power_available)
|
||||||
Route = {}
|
|
||||||
pos_already_reached(pos)
|
|
||||||
connection_walk(pos, function(pos, mem)
|
|
||||||
local pwr = PWR(pos)
|
|
||||||
if pwr and pwr.on_power then
|
|
||||||
pwr.on_power(pos)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Called from any generator on any power switching process
|
|
||||||
-- and to determine a new master in case of a timeout
|
|
||||||
local function on_power_switch(pos)
|
|
||||||
--print("on_power_change"..S(pos))
|
|
||||||
--local t = minetest.get_us_time()
|
|
||||||
local mem = tubelib2.get_mem(pos)
|
|
||||||
mem.master_pos = nil
|
|
||||||
mem.is_master = nil
|
|
||||||
-- used to check if generator is active
|
|
||||||
mem.generator_available = 2
|
|
||||||
|
|
||||||
local mpos = determine_master(pos)
|
|
||||||
store_master(pos, mpos)
|
|
||||||
--print("store_master", S(pos), S(mpos))
|
|
||||||
if mpos then
|
|
||||||
local mem = tubelib2.get_mem(mpos)
|
|
||||||
mem.is_master = true
|
|
||||||
-- trigger all nodes so that we get a stable state again
|
|
||||||
-- reset values for nect cycle
|
|
||||||
mem.needed1 = 0
|
|
||||||
mem.needed2 = 0
|
|
||||||
mem.available1 = 0
|
|
||||||
mem.available2 = 0
|
|
||||||
trigger_nodes(mpos)
|
|
||||||
accounting(tubelib2.get_mem(mpos))
|
|
||||||
--t = minetest.get_us_time() - t
|
|
||||||
--print("t = "..t)
|
|
||||||
return mem
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Generic API functions
|
|
||||||
--
|
|
||||||
techage.power = {}
|
|
||||||
|
|
||||||
techage.power.power_switched = on_power_switch
|
|
||||||
|
|
||||||
-- Used to turn on/off the power by means of a power switch
|
|
||||||
function techage.power.power_cut(pos, dir, cable, cut)
|
|
||||||
local npos = vector.add(pos, tubelib2.Dir6dToVector[dir or 0])
|
|
||||||
|
|
||||||
local node = minetest.get_node(npos)
|
|
||||||
if node.name ~= "techage:powerswitch_box" and
|
|
||||||
M(npos):get_string("techage_hidden_nodename") ~= "techage:powerswitch_box" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local mem = tubelib2.get_mem(npos)
|
|
||||||
mem.interrupted_dirs = mem.interrupted_dirs or {}
|
|
||||||
|
|
||||||
if cut then
|
|
||||||
mem.interrupted_dirs = {true, true, true, true, true, true}
|
|
||||||
for dir,_ in pairs(mem.connections) do
|
|
||||||
mem.interrupted_dirs[dir] = false
|
|
||||||
on_power_switch(npos)
|
|
||||||
trigger_nodes(npos)
|
|
||||||
mem.interrupted_dirs[dir] = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
mem.interrupted_dirs = {}
|
|
||||||
on_power_switch(npos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- only for nodes with own 'conn_sides' and rotate function
|
|
||||||
function techage.power.after_rotate_node(pos, cable)
|
|
||||||
cable:after_dig_node(pos)
|
|
||||||
set_conn_dirs(pos, PWR(pos).conn_sides)
|
|
||||||
cable:after_place_node(pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
function techage.power.register_node(names, pwr_def)
|
|
||||||
for _,name in ipairs(names) do
|
|
||||||
local ndef = minetest.registered_nodes[name]
|
|
||||||
if ndef then
|
|
||||||
minetest.override_item(name, {
|
|
||||||
power = {
|
|
||||||
conn_sides = pwr_def.conn_sides or {"L", "R", "U", "D", "F", "B"},
|
|
||||||
on_power = pwr_def.on_power,
|
|
||||||
power_network = pwr_def.power_network,
|
|
||||||
after_place_node = ndef.after_place_node,
|
|
||||||
after_dig_node = ndef.after_dig_node,
|
|
||||||
after_tube_update = ndef.after_tube_update,
|
|
||||||
},
|
|
||||||
-- after_place_node decorator
|
|
||||||
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
|
||||||
local pwr = PWR(pos)
|
|
||||||
set_conn_dirs(pos, pwr.conn_sides)
|
|
||||||
pwr.power_network:after_place_node(pos)
|
|
||||||
if pwr.after_place_node then
|
|
||||||
return pwr.after_place_node(pos, placer, itemstack, pointed_thing)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
-- after_dig_node decorator
|
|
||||||
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
|
||||||
local pwr = PWRN(oldnode)
|
|
||||||
pwr.power_network:after_dig_node(pos)
|
|
||||||
minetest.after(0.1, tubelib2.del_mem, pos) -- At latest...
|
|
||||||
if pwr.after_dig_node then
|
|
||||||
return pwr.after_dig_node(pos, oldnode, oldmetadata, digger)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
-- tubelib2 callback, called after any connection change
|
|
||||||
after_tube_update = function(node, pos, out_dir, peer_pos, peer_in_dir)
|
|
||||||
local pwr = PWR(pos)
|
|
||||||
local mem = tubelib2.get_mem(pos)
|
|
||||||
mem.connections = mem.connections or {}
|
|
||||||
if not peer_pos or not valid_indir(peer_pos, peer_in_dir)
|
|
||||||
or not valid_outdir(pos, out_dir)
|
|
||||||
or not matching_nodes(pos, peer_pos) then
|
|
||||||
mem.connections[out_dir] = nil -- del connection
|
|
||||||
else
|
|
||||||
mem.connections[out_dir] = {pos = peer_pos, in_dir = peer_in_dir}
|
|
||||||
end
|
|
||||||
-- To be called delayed, so that all network connections have been established
|
|
||||||
minetest.after(0.2, on_power_switch, pos)
|
|
||||||
if pwr.after_tube_update then
|
|
||||||
return pwr.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
pwr_def.power_network:add_secondary_node_names({name})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function techage.power.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir, power)
|
|
||||||
local mem = tubelib2.get_mem(pos)
|
|
||||||
mem.connections = mem.connections or {}
|
|
||||||
if not peer_pos or not valid_indir(peer_pos, peer_in_dir)
|
|
||||||
or not valid_outdir(pos, out_dir)
|
|
||||||
or not matching_nodes(pos, peer_pos) then
|
|
||||||
mem.connections[out_dir] = nil -- del connection
|
|
||||||
else
|
|
||||||
mem.connections[out_dir] = {pos = peer_pos, in_dir = peer_in_dir}
|
|
||||||
end
|
|
||||||
-- To be called delayed, so that all network connections have been established
|
|
||||||
minetest.after(0.2, on_power_switch, pos)
|
|
||||||
if power.after_tube_update then
|
|
||||||
return power.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Called from every generator every 2 seconds
|
|
||||||
function techage.power.power_distribution(pos)
|
|
||||||
local mem = tubelib2.get_mem(pos)
|
|
||||||
-- used to check if generator is active
|
|
||||||
mem.generator_available = 2
|
|
||||||
if mem.is_master then
|
|
||||||
-- reset values for nect cycle
|
|
||||||
mem.needed1 = 0
|
|
||||||
mem.needed2 = 0
|
|
||||||
mem.available1 = 0
|
|
||||||
mem.available2 = 0
|
|
||||||
trigger_nodes(pos, mem)
|
|
||||||
accounting(mem)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function techage.power.consume_power(pos, needed)
|
|
||||||
local master_pos = tubelib2.get_mem(pos).master_pos
|
|
||||||
--print("consume_power", S(master_pos))
|
|
||||||
if master_pos then
|
|
||||||
local mem = tubelib2.get_mem(master_pos)
|
|
||||||
-- for next cycle
|
|
||||||
mem.needed1 = (mem.needed1 or 0) + needed
|
|
||||||
-- current cycle
|
|
||||||
mem.demand1 = mem.demand1 or 0
|
|
||||||
local val = math.min(needed, mem.demand1)
|
|
||||||
mem.demand1 = mem.demand1 - val
|
|
||||||
--return val
|
|
||||||
if mem.reserve then -- TODO ????
|
|
||||||
return needed
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
function techage.power.provide_power(pos, provide)
|
|
||||||
local mem = tubelib2.get_mem(pos)
|
|
||||||
if mem.is_master then
|
|
||||||
-- nothing to do
|
|
||||||
elseif mem.master_pos then
|
|
||||||
mem = tubelib2.get_mem(mem.master_pos)
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
-- for next cycle
|
-- for next cycle
|
||||||
mem.available1 = (mem.available1 or 0) + provide
|
mst_mem.mst_available1 = mst_mem.mst_available1 + power_available
|
||||||
-- current cycle
|
-- current cycle
|
||||||
mem.supply1 = mem.supply1 or 0
|
mst_mem.mst_supply1 = mst_mem.mst_supply1 or 0
|
||||||
local val = math.min(provide, mem.supply1)
|
if mst_mem.mst_supply1 < power_available then
|
||||||
mem.supply1 = mem.supply1 - val
|
mem.pwr_provided = mst_mem.mst_supply1
|
||||||
return val
|
mst_mem.mst_supply1 = 0
|
||||||
end
|
|
||||||
|
|
||||||
function techage.power.secondary_power(pos, provide, needed)
|
|
||||||
local mem = tubelib2.get_mem(pos)
|
|
||||||
if mem.is_master then
|
|
||||||
-- nothing to do
|
|
||||||
elseif mem.master_pos then
|
|
||||||
mem = tubelib2.get_mem(mem.master_pos)
|
|
||||||
else
|
else
|
||||||
return 0
|
mst_mem.mst_supply1 = mst_mem.mst_supply1 - power_available
|
||||||
|
mem.pwr_provided = power_available
|
||||||
end
|
end
|
||||||
-- for next cycle
|
|
||||||
mem.available2 = (mem.available2 or 0) + provide
|
|
||||||
mem.needed2 = (mem.needed2 or 0) + needed
|
|
||||||
|
|
||||||
-- defensive programming
|
|
||||||
mem.supply2 = mem.supply2 or 0
|
|
||||||
mem.demand2 = mem.demand2 or 0
|
|
||||||
|
|
||||||
-- check as generator
|
|
||||||
if mem.supply2 > 0 then
|
|
||||||
local val = math.min(provide, mem.supply2)
|
|
||||||
mem.supply2 = mem.supply2 - val
|
|
||||||
return val
|
|
||||||
end
|
|
||||||
-- check as consumer
|
|
||||||
if mem.demand2 > 0 then
|
|
||||||
local val = math.min(needed, mem.demand2)
|
|
||||||
mem.demand2 = mem.demand2 - val
|
|
||||||
return -val
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function techage.power.power_available(pos, needed)
|
local function handle_consumer(mst_mem, mem, pos, power_needed)
|
||||||
local mem = tubelib2.get_mem(pos)
|
print("handle_consumer", mem.pwr_state)
|
||||||
if mem.master_pos then
|
if mem.pwr_state == NOPOWER then
|
||||||
mem = tubelib2.get_mem(mem.master_pos)
|
--print("power_needed", power_needed,"mst_mem.demand1", mst_mem.mst_demand1)
|
||||||
if needed then
|
-- for next cycle
|
||||||
-- for next cycle
|
mst_mem.mst_needed1 = mst_mem.mst_needed1 + power_needed
|
||||||
mem.needed1 = (mem.needed1 or 0) + needed
|
-- current cycle
|
||||||
|
if (mst_mem.mst_demand1 or 0) - power_needed >= 0 then
|
||||||
|
mst_mem.mst_demand1 = (mst_mem.mst_demand1 or 0) - power_needed
|
||||||
|
consumer_turn_on(pos, mem)
|
||||||
|
end
|
||||||
|
elseif mem.pwr_state == RUNNING then
|
||||||
|
-- for next cycle
|
||||||
|
mst_mem.mst_needed1 = mst_mem.mst_needed1 + power_needed
|
||||||
|
-- current cycle
|
||||||
|
mst_mem.mst_demand1 = (mst_mem.mst_demand1 or 0) - power_needed
|
||||||
|
if mst_mem.mst_demand1 < 0 then
|
||||||
|
mst_mem.mst_demand1 = 0
|
||||||
|
consumer_turn_off(pos, mem)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function handle_secondary(mst_mem, mem, pos, provides, needed)
|
||||||
|
-- for next cycle
|
||||||
|
mst_mem.mst_available2 = (mst_mem.mst_available2 or 0) + provides
|
||||||
|
mst_mem.mst_needed2 = (mst_mem.mst_needed2 or 0) + needed
|
||||||
|
-- check as generator
|
||||||
|
mst_mem.mst_supply2 = mst_mem.mst_supply2 or 0
|
||||||
|
mst_mem.mst_demand2 = mst_mem.mst_demand2 or 0
|
||||||
|
if mst_mem.mst_supply2 > 0 then
|
||||||
|
local val = math.min(provides, mst_mem.mst_supply2)
|
||||||
|
mst_mem.mst_supply2 = mst_mem.mst_supply2 - val
|
||||||
|
mem.pwr_provided = val
|
||||||
|
-- check as consumer
|
||||||
|
elseif mst_mem.mst_demand2 > 0 then
|
||||||
|
local val = math.min(needed, mst_mem.mst_demand2)
|
||||||
|
mst_mem.mst_demand2 = mst_mem.mst_demand2 - val
|
||||||
|
mem.pwr_provided = -val
|
||||||
|
else
|
||||||
|
mem.pwr_provided = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function trigger_nodes(mst_pos, mst_mem)
|
||||||
|
Route = {}
|
||||||
|
pos_already_reached(mst_pos)
|
||||||
|
connection_walk(mst_pos, function(pos, mem)
|
||||||
|
mem.pwr_node_alive_cnt = (mem.pwr_node_alive_cnt or 1) - 1
|
||||||
|
mem.pwr_power_provided_cnt = 2
|
||||||
|
--print("trigger_nodes", mem.pwr_node_alive_cnt, mem.pwr_available2 or mem.pwr_available or mem.pwr_needed)
|
||||||
|
if mem.pwr_node_alive_cnt >= 0 then
|
||||||
|
if mem.pwr_available then
|
||||||
|
handle_generator(mst_mem, mem, pos, mem.pwr_available)
|
||||||
|
elseif mem.pwr_needed then
|
||||||
|
handle_consumer(mst_mem, mem, pos, mem.pwr_needed)
|
||||||
|
elseif mem.pwr_available2 then
|
||||||
|
handle_secondary(mst_mem, mem, pos, mem.pwr_available2, mem.pwr_needed2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function determine_new_master(pos, mem)
|
||||||
|
local was_master = mem.pwr_is_master
|
||||||
|
mem.pwr_is_master = false
|
||||||
|
local mpos = determine_master(pos)
|
||||||
|
--print("determine_new_master", S(mpos))
|
||||||
|
store_master(pos, mpos)
|
||||||
|
if mpos then
|
||||||
|
tubelib2.get_mem(mpos).pwr_is_master = true
|
||||||
|
elseif was_master then -- no master any more
|
||||||
|
-- delete data
|
||||||
|
local mmem = tubelib2.get_mem(mpos)
|
||||||
|
mmem.mst_supply1 = 0
|
||||||
|
mmem.mst_supply2 = 0
|
||||||
|
mmem.mst_reserve = 0
|
||||||
|
end
|
||||||
|
return was_master or mem.pwr_is_master
|
||||||
|
end
|
||||||
|
|
||||||
|
-- called from master position
|
||||||
|
local function power_distribution(pos, mem)
|
||||||
|
mem.mst_needed1 = 0
|
||||||
|
mem.mst_needed2 = 0
|
||||||
|
mem.mst_available1 = 0
|
||||||
|
mem.mst_available2 = 0
|
||||||
|
trigger_nodes(pos, mem)
|
||||||
|
accounting(pos, mem)
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Power API functions
|
||||||
|
--
|
||||||
|
|
||||||
|
-- To be called for each network change from any node
|
||||||
|
function techage.power.network_changed(pos, mem)
|
||||||
|
print("network_changed")
|
||||||
|
mem.pwr_node_alive_cnt = (mem.pwr_cycle_time or 2)/2 + 1
|
||||||
|
if determine_new_master(pos, mem) then -- new master?
|
||||||
|
power_distribution(pos, mem)
|
||||||
|
elseif not next(mem.connections) then -- isolated?
|
||||||
|
if mem.pwr_needed then -- consumer?
|
||||||
|
consumer_turn_off(pos, mem)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Generator related functions
|
||||||
|
--
|
||||||
|
function techage.power.generator_start(pos, mem, available)
|
||||||
|
mem.pwr_node_alive_cnt = 2
|
||||||
|
mem.pwr_cycle_time = 2
|
||||||
|
mem.pwr_available = available
|
||||||
|
if determine_new_master(pos, mem) then -- new master
|
||||||
|
power_distribution(pos, mem)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function techage.power.generator_stop(pos, mem)
|
||||||
|
mem.pwr_node_alive_cnt = 0
|
||||||
|
mem.pwr_available = 0
|
||||||
|
if determine_new_master(pos, mem) then -- last available master
|
||||||
|
power_distribution(pos, mem)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function techage.power.generator_alive(pos, mem)
|
||||||
|
mem.pwr_node_alive_cnt = 2
|
||||||
|
if mem.pwr_is_master then
|
||||||
|
power_distribution(pos, mem)
|
||||||
|
end
|
||||||
|
return mem.pwr_provided
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Consumer related functions
|
||||||
|
--
|
||||||
|
function techage.power.consumer_alive(pos, mem)
|
||||||
|
print("consumer_alive", mem.pwr_power_provided_cnt)
|
||||||
|
mem.pwr_power_provided_cnt = (mem.pwr_power_provided_cnt or 0) - (mem.pwr_cycle_time or 2)/2
|
||||||
|
if mem.pwr_power_provided_cnt >= 0 then
|
||||||
|
mem.pwr_node_alive_cnt = (mem.pwr_cycle_time or 2)/2 + 1
|
||||||
|
else
|
||||||
|
consumer_turn_off(pos, mem)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function techage.power.consumer_start(pos, mem, cycle_time, needed)
|
||||||
|
mem.pwr_cycle_time = cycle_time
|
||||||
|
mem.pwr_power_provided_cnt = 0
|
||||||
|
mem.pwr_node_alive_cnt = 2
|
||||||
|
mem.pwr_needed = needed
|
||||||
|
mem.pwr_state = NOPOWER
|
||||||
|
end
|
||||||
|
|
||||||
|
function techage.power.consumer_stop(pos, mem)
|
||||||
|
mem.pwr_power_provided_cnt = 0
|
||||||
|
mem.pwr_node_alive_cnt = 0
|
||||||
|
mem.pwr_needed = 0
|
||||||
|
mem.pwr_state = STOPPED
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Lamp related function to speed up the turn on
|
||||||
|
function techage.power.power_available(pos, mem, needed)
|
||||||
|
if mem.pwr_master_pos and (mem.pwr_power_provided_cnt or 0) > 0 then
|
||||||
|
mem = tubelib2.get_mem(mem.pwr_master_pos)
|
||||||
|
if (mem.mst_reserve or 0) - needed >= 0 then
|
||||||
|
mem.mst_reserve = mem.mst_reserve - needed
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
return mem.reserve
|
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
function techage.power.power_accounting(pos)
|
-- Power terminal function
|
||||||
local mem = tubelib2.get_mem(pos)
|
function techage.power.power_accounting(pos, mem)
|
||||||
if mem.master_pos then
|
if mem.pwr_master_pos then
|
||||||
mem = tubelib2.get_mem(mem.master_pos)
|
mem = tubelib2.get_mem(mem.pwr_master_pos)
|
||||||
return "\nGenerators = "..mem.available1.."\nAkkus = "..mem.available2.."\nMachines = "..mem.needed1.."\n"
|
return {
|
||||||
|
prim_available = mem.mst_available1,
|
||||||
|
sec_available = mem.mst_available2,
|
||||||
|
prim_needed = mem.mst_needed1,
|
||||||
|
sec_needed = mem.mst_needed2,
|
||||||
|
}
|
||||||
end
|
end
|
||||||
return "no power"
|
return {
|
||||||
|
prim_available = 0,
|
||||||
|
sec_available = 0,
|
||||||
|
prim_needed = 0,
|
||||||
|
sec_needed = 0,
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function techage.power.percent(max_val, curr_val)
|
--
|
||||||
return math.min(math.ceil(((curr_val or 0) * 100.0) / (max_val or 1.0)), 100)
|
-- Akku related functions
|
||||||
|
--
|
||||||
|
function techage.power.secondary_start(pos, mem, available, needed)
|
||||||
|
mem.pwr_node_alive_cnt = 2
|
||||||
|
mem.pwr_could_provide = available
|
||||||
|
mem.pwr_could_need = needed
|
||||||
|
if determine_new_master(pos, mem) then -- new master
|
||||||
|
power_distribution(pos, mem)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function techage.power.formspec_load_bar(charging, max_val)
|
function techage.power.secondary_stop(pos, mem)
|
||||||
local percent
|
mem.pwr_node_alive_cnt = 0
|
||||||
charging = charging or 0
|
mem.pwr_could_provide = 0
|
||||||
max_val = max_val or 1
|
mem.pwr_could_need = 0
|
||||||
if charging ~= 0 then
|
if determine_new_master(pos, mem) then -- last available master
|
||||||
percent = 50 + math.ceil((charging * 50.0) / max_val)
|
power_distribution(pos, mem)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if charging > 0 then
|
function techage.power.secondary_alive(pos, mem, capa_curr, capa_max)
|
||||||
return "techage_form_level_off.png^[lowpart:"..percent..":techage_form_level_charge.png"
|
--print("secondary_alive")
|
||||||
elseif charging < 0 then
|
if capa_curr >= capa_max then
|
||||||
return "techage_form_level_unload.png^[lowpart:"..percent..":techage_form_level_off.png"
|
mem.pwr_available2, mem.pwr_needed2 = mem.pwr_could_provide, 0 -- can provide only
|
||||||
|
elseif capa_curr <= 0 then
|
||||||
|
mem.pwr_available2, mem.pwr_needed2 = 0, mem.pwr_could_need -- can deliver only
|
||||||
else
|
else
|
||||||
return "techage_form_level_off.png"
|
mem.pwr_available2, mem.pwr_needed2 = mem.pwr_could_provide, mem.pwr_could_need
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
mem.pwr_node_alive_cnt = 2
|
||||||
function techage.power.formspec_power_bar(max_power, current_power)
|
if mem.pwr_is_master then
|
||||||
local percent = techage.power.percent(max_power, current_power)
|
--print("secondary_alive is master")
|
||||||
percent = (percent + 5) / 1.22 -- texture correction
|
power_distribution(pos, mem)
|
||||||
return "techage_form_level_bg.png^[lowpart:"..percent..":techage_form_level_fg.png"
|
end
|
||||||
end
|
return mem.pwr_provided
|
||||||
|
end
|
||||||
|
|
||||||
function techage.power.side_to_outdir(pos, side)
|
|
||||||
local node = minetest.get_node(pos)
|
|
||||||
return side_to_dir(node.param2, side)
|
|
||||||
end
|
|
224
power/power2.lua
Normal file
224
power/power2.lua
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
--[[
|
||||||
|
|
||||||
|
TechAge
|
||||||
|
=======
|
||||||
|
|
||||||
|
Copyright (C) 2019 Joachim Stolberg
|
||||||
|
|
||||||
|
LGPLv2.1+
|
||||||
|
See LICENSE.txt for more information
|
||||||
|
|
||||||
|
Power helper functions
|
||||||
|
]]--
|
||||||
|
|
||||||
|
-- for lazy programmers
|
||||||
|
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
|
||||||
|
local P = minetest.string_to_pos
|
||||||
|
local M = minetest.get_meta
|
||||||
|
-- Techage Related Data
|
||||||
|
local PWR = function(pos) return (minetest.registered_nodes[minetest.get_node(pos).name] or {}).power end
|
||||||
|
local PWRN = function(node) return (minetest.registered_nodes[node.name] or {}).power end
|
||||||
|
|
||||||
|
local network_changed = techage.power.network_changed
|
||||||
|
|
||||||
|
local SideToDir = {B=1, R=2, F=3, L=4, D=5, U=6}
|
||||||
|
|
||||||
|
local function side_to_dir(param2, side)
|
||||||
|
local dir = SideToDir[side]
|
||||||
|
if dir < 5 then
|
||||||
|
dir = (((dir - 1) + (param2 % 4)) % 4) + 1
|
||||||
|
end
|
||||||
|
return dir
|
||||||
|
end
|
||||||
|
|
||||||
|
local function set_conn_dirs(pos, sides)
|
||||||
|
local tbl = {}
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
if type(sides) == "function" then
|
||||||
|
tbl = sides(pos, node)
|
||||||
|
else
|
||||||
|
for _,side in ipairs(sides) do
|
||||||
|
tbl[#tbl+1] = tubelib2.Turn180Deg[side_to_dir(node.param2, side)]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
M(pos):set_string("power_dirs", minetest.serialize(tbl))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function valid_indir(pos, in_dir)
|
||||||
|
local s = M(pos):get_string("power_dirs")
|
||||||
|
if s == "" then
|
||||||
|
local pwr = PWR(pos)
|
||||||
|
if pwr then
|
||||||
|
set_conn_dirs(pos, pwr.conn_sides)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if s ~= "" then
|
||||||
|
for _,dir in ipairs(minetest.deserialize(s)) do
|
||||||
|
if dir == in_dir then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function valid_outdir(pos, out_dir)
|
||||||
|
return valid_indir(pos, tubelib2.Turn180Deg[out_dir])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Both nodes are from the same power network type?
|
||||||
|
local function matching_nodes(pos, peer_pos)
|
||||||
|
local tube_type1 = pos and PWR(pos) and PWR(pos).power_network.tube_type
|
||||||
|
local tube_type2 = peer_pos and PWR(peer_pos) and PWR(peer_pos).power_network.tube_type
|
||||||
|
return not tube_type1 or not tube_type2 or tube_type1 == tube_type2
|
||||||
|
end
|
||||||
|
|
||||||
|
function techage.get_pos(pos, side)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
local dir = nil
|
||||||
|
if node.name ~= "air" and node.name ~= "ignore" then
|
||||||
|
dir = side_to_dir(node.param2, side)
|
||||||
|
end
|
||||||
|
return tubelib2.get_pos(pos, dir)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- only for nodes with own 'conn_sides' and rotate function
|
||||||
|
function techage.power.after_rotate_node(pos, cable)
|
||||||
|
cable:after_dig_node(pos)
|
||||||
|
set_conn_dirs(pos, PWR(pos).conn_sides)
|
||||||
|
cable:after_place_node(pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
function techage.power.register_node(names, pwr_def)
|
||||||
|
for _,name in ipairs(names) do
|
||||||
|
local ndef = minetest.registered_nodes[name]
|
||||||
|
if ndef then
|
||||||
|
minetest.override_item(name, {
|
||||||
|
power = {
|
||||||
|
conn_sides = pwr_def.conn_sides or {"L", "R", "U", "D", "F", "B"},
|
||||||
|
on_power = pwr_def.on_power,
|
||||||
|
on_nopower = pwr_def.on_nopower,
|
||||||
|
power_network = pwr_def.power_network,
|
||||||
|
after_place_node = ndef.after_place_node,
|
||||||
|
after_dig_node = ndef.after_dig_node,
|
||||||
|
after_tube_update = ndef.after_tube_update,
|
||||||
|
},
|
||||||
|
-- after_place_node decorator
|
||||||
|
after_place_node = function(pos, placer, itemstack, pointed_thing)
|
||||||
|
local pwr = PWR(pos)
|
||||||
|
set_conn_dirs(pos, pwr.conn_sides)
|
||||||
|
pwr.power_network:after_place_node(pos)
|
||||||
|
if pwr.after_place_node then
|
||||||
|
return pwr.after_place_node(pos, placer, itemstack, pointed_thing)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
-- after_dig_node decorator
|
||||||
|
after_dig_node = function(pos, oldnode, oldmetadata, digger)
|
||||||
|
local pwr = PWRN(oldnode)
|
||||||
|
pwr.power_network:after_dig_node(pos)
|
||||||
|
minetest.after(0.1, tubelib2.del_mem, pos) -- At latest...
|
||||||
|
if pwr.after_dig_node then
|
||||||
|
return pwr.after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
-- tubelib2 callback, called after any connection change
|
||||||
|
after_tube_update = function(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||||
|
local pwr = PWR(pos)
|
||||||
|
local mem = tubelib2.get_mem(pos)
|
||||||
|
mem.connections = mem.connections or {}
|
||||||
|
if not peer_pos or not valid_indir(peer_pos, peer_in_dir)
|
||||||
|
or not valid_outdir(pos, out_dir)
|
||||||
|
or not matching_nodes(pos, peer_pos) then
|
||||||
|
mem.connections[out_dir] = nil -- del connection
|
||||||
|
else
|
||||||
|
mem.connections[out_dir] = {pos = peer_pos, in_dir = peer_in_dir}
|
||||||
|
end
|
||||||
|
-- To be called delayed, so that all network connections have been established
|
||||||
|
minetest.after(0.2, network_changed, pos, mem)
|
||||||
|
if pwr.after_tube_update then
|
||||||
|
return pwr.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
pwr_def.power_network:add_secondary_node_names({name})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function techage.power.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir, power)
|
||||||
|
local mem = tubelib2.get_mem(pos)
|
||||||
|
mem.connections = mem.connections or {}
|
||||||
|
if not peer_pos or not valid_indir(peer_pos, peer_in_dir)
|
||||||
|
or not valid_outdir(pos, out_dir)
|
||||||
|
or not matching_nodes(pos, peer_pos) then
|
||||||
|
mem.connections[out_dir] = nil -- del connection
|
||||||
|
else
|
||||||
|
mem.connections[out_dir] = {pos = peer_pos, in_dir = peer_in_dir}
|
||||||
|
end
|
||||||
|
-- To be called delayed, so that all network connections have been established
|
||||||
|
minetest.after(0.2, network_changed, pos, mem)
|
||||||
|
if power.after_tube_update then
|
||||||
|
return power.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function techage.power.percent(max_val, curr_val)
|
||||||
|
return math.min(math.ceil(((curr_val or 0) * 100.0) / (max_val or 1.0)), 100)
|
||||||
|
end
|
||||||
|
|
||||||
|
function techage.power.formspec_load_bar(charging, max_val)
|
||||||
|
local percent
|
||||||
|
charging = charging or 0
|
||||||
|
max_val = max_val or 1
|
||||||
|
if charging ~= 0 then
|
||||||
|
percent = 50 + math.ceil((charging * 50.0) / max_val)
|
||||||
|
end
|
||||||
|
|
||||||
|
if charging > 0 then
|
||||||
|
return "techage_form_level_off.png^[lowpart:"..percent..":techage_form_level_charge.png"
|
||||||
|
elseif charging < 0 then
|
||||||
|
return "techage_form_level_unload.png^[lowpart:"..percent..":techage_form_level_off.png"
|
||||||
|
else
|
||||||
|
return "techage_form_level_off.png"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function techage.power.formspec_power_bar(max_power, current_power)
|
||||||
|
local percent = techage.power.percent(max_power, current_power)
|
||||||
|
percent = (percent + 5) / 1.22 -- texture correction
|
||||||
|
return "techage_form_level_bg.png^[lowpart:"..percent..":techage_form_level_fg.png"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function techage.power.side_to_outdir(pos, side)
|
||||||
|
local node = minetest.get_node(pos)
|
||||||
|
return side_to_dir(node.param2, side)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Used to turn on/off the power by means of a power switch
|
||||||
|
function techage.power.power_cut(pos, dir, cable, cut)
|
||||||
|
local npos = vector.add(pos, tubelib2.Dir6dToVector[dir or 0])
|
||||||
|
|
||||||
|
local node = minetest.get_node(npos)
|
||||||
|
if node.name ~= "techage:powerswitch_box" and
|
||||||
|
M(npos):get_string("techage_hidden_nodename") ~= "techage:powerswitch_box" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local mem = tubelib2.get_mem(npos)
|
||||||
|
mem.interrupted_dirs = mem.interrupted_dirs or {}
|
||||||
|
|
||||||
|
if cut then
|
||||||
|
mem.interrupted_dirs = {true, true, true, true, true, true}
|
||||||
|
for dir,_ in pairs(mem.connections) do
|
||||||
|
mem.interrupted_dirs[dir] = false
|
||||||
|
techage.power.network_changed(pos, mem)
|
||||||
|
mem.interrupted_dirs[dir] = true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
mem.interrupted_dirs = {}
|
||||||
|
techage.power.network_changed(pos, mem)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -74,7 +74,8 @@ local function read_state(itemstack, user, pointed_thing)
|
|||||||
elseif ndef and ndef.description then
|
elseif ndef and ndef.description then
|
||||||
if ndef.is_power_available then
|
if ndef.is_power_available then
|
||||||
local power = ndef.is_power_available(pos)
|
local power = ndef.is_power_available(pos)
|
||||||
minetest.chat_send_player(user:get_player_name(), ndef.description..": power = "..power.." ")
|
local text = "\nGenerators = "..power.prim_available.."\nAkkus = "..power.sec_available.."\nMachines = "..power.prim_needed.."\n"
|
||||||
|
minetest.chat_send_player(user:get_player_name(), ndef.description..": power = "..text)
|
||||||
end
|
end
|
||||||
itemstack:add_wear(65636/200)
|
itemstack:add_wear(65636/200)
|
||||||
return itemstack
|
return itemstack
|
||||||
|
Loading…
x
Reference in New Issue
Block a user