Merge branch 'networks'

This commit is contained in:
Joachim Stolberg 2021-07-23 19:47:43 +02:00
commit 8e249248dc
130 changed files with 4653 additions and 5546 deletions

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
@ -21,7 +21,8 @@ local PWR_NEEDED = 5
local CYCLE_TIME = 2
local Cable = techage.ElectricCable
local power = techage.power
--local Cable = techage.Axle
local power = networks.power
local function swap_node(pos, name)
local node = techage.get_node_lvm(pos)
@ -32,39 +33,18 @@ local function swap_node(pos, name)
minetest.swap_node(pos, node)
end
local function on_power(pos)
--print("on_power sink "..P2S(pos))
swap_node(pos, "techage:sink_on")
M(pos):set_string("infotext", "on")
end
local function on_nopower(pos)
--print("on_nopower sink "..P2S(pos))
swap_node(pos, "techage:sink")
M(pos):set_string("infotext", "off")
end
local function node_timer(pos, elapsed)
--print("node_timer sink "..P2S(pos))
local nvm = techage.get_nvm(pos)
power.consumer_alive(pos, Cable, CYCLE_TIME)
return true
end
local function on_rightclick(pos, node, clicker)
local nvm = techage.get_nvm(pos)
if not nvm.running and power.power_available(pos, Cable) then
nvm.running = true
-- swap will be performed via on_power()
power.consumer_start(pos, Cable, CYCLE_TIME)
swap_node(pos, "techage:sink_on")
M(pos):set_string("infotext", "on")
minetest.get_node_timer(pos):start(CYCLE_TIME)
M(pos):set_string("infotext", "...")
else
nvm.running = false
swap_node(pos, "techage:sink")
power.consumer_stop(pos, Cable)
minetest.get_node_timer(pos):stop()
M(pos):set_string("infotext", "off")
minetest.get_node_timer(pos):stop()
end
end
@ -79,30 +59,21 @@ local function after_dig_node(pos, oldnode)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
end
local net_def = {
ele1 = {
sides = techage.networks.AllSides, -- Cable connection sides
ntype = "con1",
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED,
},
}
minetest.register_node("techage:sink", {
description = "Sink",
tiles = {'techage_electric_button.png'},
tiles = {'techage_electric_button.png^[colorize:#000000:50'},
on_timer = node_timer,
on_timer = function(pos, elapsed)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed == PWR_NEEDED then
swap_node(pos, "techage:sink_on")
M(pos):set_string("infotext", "on")
end
return true
end,
on_rightclick = on_rightclick,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
paramtype = "light",
light_source = 0,
@ -116,12 +87,17 @@ minetest.register_node("techage:sink_on", {
description = "Sink",
tiles = {'techage_electric_button.png'},
on_timer = node_timer,
on_timer = function(pos, elapsed)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed < PWR_NEEDED then
swap_node(pos, "techage:sink")
M(pos):set_string("infotext", "off")
end
return true
end,
on_rightclick = on_rightclick,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
paramtype = "light",
light_source = minetest.LIGHT_MAX,
@ -133,5 +109,4 @@ minetest.register_node("techage:sink_on", {
sounds = default.node_sound_wood_defaults(),
})
Cable:add_secondary_node_names({"techage:sink", "techage:sink_on"})
power.register_nodes({"techage:sink", "techage:sink_on"}, Cable, "con")

View File

@ -31,11 +31,11 @@ Copyright (C) 2019-2021 Joachim Stolberg
Code: Licensed under the GNU AGPL version 3 or later. See LICENSE.txt
Textures: CC BY-SA 3.0
Many thanks to Thomas-S for his contributions
Many thanks to Thomas-S and others for their contributions
### Dependencies
Required: default, doors, bucket, stairs, screwdriver, basic_materials, tubelib2, minecart, lcdlib, safer_lua
Required: default, doors, bucket, stairs, screwdriver, basic_materials, tubelib2, networks, minecart, lcdlib, safer_lua
Recommended: signs_bot, hyperloop, compost, techpack_stairway, autobahn
Optional: unified_inventory, wielded_light, unifieddyes, lua-mashal, lsqlite3, moreores, ethereal, mesecon
@ -46,6 +46,7 @@ The mods `default`, `doors`, `bucket`, `stairs`, and `screwdriver` are part of M
The following mods in the newest version have to be downloaded directly from GitHub:
* [tubelib2](https://github.com/joe7575/tubelib2)
* [networks](https://github.com/joe7575/networks)
* [minecart](https://github.com/joe7575/minecart)
* [lcdlib](https://github.com/joe7575/lcdlib)
* [safer_lua](https://github.com/joe7575/safer_lua)
@ -77,6 +78,15 @@ Available worlds will be converted to 'lsqlite3', but there is no way back, so:
### History
**2021-07-18 V1.00**
- Change the way, power distribution works
- Add TA2 storage system
- Add TA4 Isolation Transformer
- Add TA4 Electric Meter
- Add new power terminal
- Many improvements on power producing/consuming nodes
- See Construction Board for some hints on moving to v1
**2021-05-14 V0.25**
- Add concentrator tubes
- Add ta4 cable wall entry

View File

@ -16,7 +16,6 @@
local M = minetest.get_meta
local S = techage.S
local networks = techage.networks
local Tube = techage.Tube
local size = 2/8
@ -29,7 +28,7 @@ local Boxes = {
{{-size, -size, -size, size, 0.5, size}}, -- y+
}
local names = techage.register_junction("techage:concentrator", 2/8, Boxes, Tube, {
local names = networks.register_junction("techage:concentrator", 2/8, Boxes, Tube, {
description = S("Tube Concentrator"),
tiles = {
"techage_tube_junction.png^techage_appl_arrow2.png^[transformR270",
@ -45,13 +44,13 @@ local names = techage.register_junction("techage:concentrator", 2/8, Boxes, Tube
after_place_node = function(pos, placer, itemstack, pointed_thing)
local node = minetest.get_node(pos)
local name = "techage:concentrator"..techage.junction_type(pos, Tube, "R", node.param2)
local name = "techage:concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
minetest.swap_node(pos, {name = name, param2 = node.param2})
M(pos):set_int("push_dir", techage.side_to_outdir("R", node.param2))
Tube:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, dir1, tlib2, node)
local name = "techage:concentrator"..techage.junction_type(pos, Tube, "R", node.param2)
local name = "techage:concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
minetest.swap_node(pos, {name = name, param2 = node.param2})
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
@ -67,7 +66,7 @@ techage.register_node(names, {
is_pusher = true, -- is a pulling/pushing node
})
names = techage.register_junction("techage:ta4_concentrator", 2/8, Boxes, Tube, {
names = networks.register_junction("techage:ta4_concentrator", 2/8, Boxes, Tube, {
description = S("TA4 Tube Concentrator"),
tiles = {
"techage_tubeta4_junction.png^techage_appl_arrow2.png^[transformR270",
@ -83,13 +82,13 @@ names = techage.register_junction("techage:ta4_concentrator", 2/8, Boxes, Tube,
after_place_node = function(pos, placer, itemstack, pointed_thing)
local node = minetest.get_node(pos)
local name = "techage:ta4_concentrator"..techage.junction_type(pos, Tube, "R", node.param2)
local name = "techage:ta4_concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
minetest.swap_node(pos, {name = name, param2 = node.param2})
M(pos):set_int("push_dir", techage.side_to_outdir("R", node.param2))
Tube:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, dir1, tlib2, node)
local name = "techage:ta4_concentrator"..techage.junction_type(pos, Tube, "R", node.param2)
local name = "techage:ta4_concentrator"..networks.junction_type(pos, Tube, "R", node.param2)
minetest.swap_node(pos, {name = name, param2 = node.param2})
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)

View File

@ -27,10 +27,18 @@ local M = minetest.get_meta
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
local CRDN = function(node) return (minetest.registered_nodes[node.name] or {}).consumer end
local power = techage.power
local networks = techage.networks
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local Tube = techage.Tube
local power = networks.power
local liquid = networks.liquid
local CYCLE_TIME = 2
local function get_keys(tbl)
local keys = {}
for k,v in pairs(tbl) do
keys[#keys + 1] = k
end
return keys
end
local function has_power(pos, nvm, state)
local crd = CRD(pos)
@ -38,37 +46,53 @@ local function has_power(pos, nvm, state)
end
local function start_node(pos, nvm, state)
local crd = CRD(pos)
power.consumer_start(pos, crd.power_netw, crd.cycle_time)
end
local function stop_node(pos, nvm, state)
local crd = CRD(pos)
power.consumer_stop(pos, crd.power_netw)
end
local function on_power(pos)
local crd = CRD(pos)
local nvm = techage.get_nvm(pos)
crd.State:start(pos, nvm)
end
local function on_nopower(pos)
local crd = CRD(pos)
local nvm = techage.get_nvm(pos)
crd.State:nopower(pos, nvm)
end
local function node_timer(pos, elapsed)
local function node_timer_pas(pos, elapsed)
local crd = CRD(pos)
local nvm = techage.get_nvm(pos)
-- handle power consumption
if crd.power_netw and techage.needs_power(nvm) then
power.consumer_alive(pos, crd.power_netw, crd.cycle_time)
local consumed = power.consume_power(pos, crd.power_netw, nil, crd.power_consumption)
if consumed == crd.power_consumption then
crd.State:start(pos, nvm)
end
end
-- call the node timer routine
if techage.is_operational(nvm) then
nvm.node_timer_call_cyle = (nvm.node_timer_call_cyle or 0) + 1
if nvm.node_timer_call_cyle >= crd.call_cycle then
crd.node_timer(pos, crd.cycle_time)
nvm.node_timer_call_cyle = 0
end
end
return crd.State:is_active(nvm)
end
local function node_timer_act(pos, elapsed)
local crd = CRD(pos)
local nvm = techage.get_nvm(pos)
-- handle power consumption
if crd.power_netw and techage.needs_power(nvm) then
local consumed = power.consume_power(pos, crd.power_netw, nil, crd.power_consumption)
if consumed < crd.power_consumption then
crd.State:nopower(pos, nvm)
end
end
-- call the node timer routine
if techage.is_operational(nvm) then
crd.node_timer(pos, crd.cycle_time)
nvm.node_timer_call_cyle = (nvm.node_timer_call_cyle or 0) + 1
if nvm.node_timer_call_cyle >= crd.call_cycle then
crd.node_timer(pos, crd.cycle_time)
nvm.node_timer_call_cyle = 0
end
end
return crd.State:is_active(nvm)
end
@ -105,37 +129,17 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
local power_network
local power_png = 'techage_axle_clutch.png'
local power_used = tNode.power_consumption ~= nil
local tNetworks
local sides
-- power needed?
if power_used then
if stage > 2 then
power_network = techage.ElectricCable
power_png = 'techage_appl_hole_electric.png'
tNetworks = {
ele1 = {
sides = tNode.power_sides or {F=1, B=1, U=1, D=1},
ntype = "con1",
nominal = tNode.power_consumption[stage],
on_power = on_power,
on_nopower = on_nopower,
is_running = function(pos, nvm) return techage.is_running(nvm) end,
},
}
if tNode.networks and tNode.networks.pipe2 then
tNetworks.pipe2 = tNode.networks.pipe2
end
sides = get_keys(tNode.power_sides or {F=1, B=1, U=1, D=1})
else
power_network = techage.Axle
power_png = 'techage_axle_clutch.png'
tNetworks = {
axle = {
sides = tNode.power_sides or {F=1, B=1, U=1, D=1},
ntype = "con1",
nominal = tNode.power_consumption[stage],
on_power = on_power,
on_nopower = on_nopower,
}
}
sides = get_keys(tNode.power_sides or {F=1, B=1, U=1, D=1})
end
end
@ -143,7 +147,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
node_name_passive = name_pas,
node_name_active = name_act,
infotext_name = name_inv,
cycle_time = tNode.cycle_time,
cycle_time = CYCLE_TIME,
standby_ticks = tNode.standby_ticks,
formspec_func = tNode.formspec,
on_state_change = tNode.on_state_change,
@ -162,6 +166,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
tNode.power_consumption[stage] or 0,
node_timer = tNode.node_timer,
cycle_time = tNode.cycle_time,
call_cycle = tNode.cycle_time / 2,
power_netw = power_network,
}
@ -198,17 +203,6 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
techage.del_mem(pos)
end
local tubelib2_on_update2 = function(pos, outdir, tlib2, node)
if tNode.tubelib2_on_update2 then
tNode.tubelib2_on_update2(pos, outdir, tlib2, node)
end
if tlib2.tube_type == "pipe2" then
liquid.update_network(pos, outdir, tlib2)
else
power.update_network(pos, outdir, tlib2)
end
end
tNode.groups.not_in_creative_inventory = 0
local def_pas = {
@ -221,20 +215,18 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
can_dig = tNode.can_dig,
on_rotate = tNode.on_rotate or screwdriver.disallow,
on_timer = node_timer,
on_timer = node_timer_pas,
on_receive_fields = tNode.on_receive_fields,
on_rightclick = tNode.on_rightclick,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
preserve_metadata = tNode.preserve_metadata,
tubelib2_on_update2 = tubelib2_on_update2,
allow_metadata_inventory_put = tNode.allow_metadata_inventory_put,
allow_metadata_inventory_move = tNode.allow_metadata_inventory_move,
allow_metadata_inventory_take = tNode.allow_metadata_inventory_take,
on_metadata_inventory_move = tNode.on_metadata_inventory_move,
on_metadata_inventory_put = tNode.on_metadata_inventory_put,
on_metadata_inventory_take = tNode.on_metadata_inventory_take,
networks = tNetworks and table.copy(tNetworks),
paramtype = tNode.paramtype,
paramtype2 = "facedir",
@ -264,19 +256,17 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
selection_box = tNode.selection_box,
on_rotate = tNode.on_rotate or screwdriver.disallow,
on_timer = node_timer,
on_timer = node_timer_act,
on_receive_fields = tNode.on_receive_fields,
on_rightclick = tNode.on_rightclick,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
allow_metadata_inventory_put = tNode.allow_metadata_inventory_put,
allow_metadata_inventory_move = tNode.allow_metadata_inventory_move,
allow_metadata_inventory_take = tNode.allow_metadata_inventory_take,
on_metadata_inventory_move = tNode.on_metadata_inventory_move,
on_metadata_inventory_put = tNode.on_metadata_inventory_put,
on_metadata_inventory_take = tNode.on_metadata_inventory_take,
networks = tNetworks and table.copy(tNetworks),
paramtype = tNode.paramtype,
paramtype2 = "facedir",
@ -297,9 +287,14 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState
minetest.register_node(name_act, def_act)
if power_used then
power_network:add_secondary_node_names({name_pas, name_act})
power.register_nodes({name_pas, name_act}, power_network, "con", sides)
end
techage.register_node({name_pas, name_act}, tNode.tubing)
if tNode.tube_sides then
Tube:set_valid_sides(name_pas, get_keys(tNode.tube_sides))
Tube:set_valid_sides(name_act, get_keys(tNode.tube_sides))
end
end
end
return names[1], names[2], names[3]

View File

@ -357,7 +357,7 @@ local function on_receive_fields(pos, formname, fields, player)
end
local meta = M(pos)
local crd = CRD(pos)
local filter = minetest.deserialize(meta:get_string("filter"))
local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false}
if fields.filter1 ~= nil then
filter[1] = fields.filter1 == "true"
elseif fields.filter2 ~= nil then
@ -385,7 +385,7 @@ end
local function change_filter_settings(pos, slot, val)
local slots = {["red"] = 1, ["green"] = 2, ["blue"] = 3, ["yellow"] = 4}
local meta = M(pos)
local filter = minetest.deserialize(meta:get_string("filter"))
local filter = minetest.deserialize(meta:get_string("filter")) or {false,false,false,false}
local num = slots[slot] or 1
if num >= 1 and num <= 4 then
filter[num] = val == "on"
@ -402,7 +402,7 @@ end
-- techage command to read filter channel status (on/off)
local function read_filter_settings(pos, slot)
local slots = {["red"] = 1, ["green"] = 2, ["blue"] = 3, ["yellow"] = 4}
local filter = minetest.deserialize(M(pos):get_string("filter"))
local filter = minetest.deserialize(M(pos):get_string("filter")) or {false,false,false,false}
return filter[slots[slot]] and "on" or "off"
end

View File

@ -293,6 +293,7 @@ local node_name_ta2, node_name_ta3, node_name_ta4 =
sounds = default.node_sound_wood_defaults(),
num_items = {0,1,1,1},
power_consumption = {0,3,3,3},
tube_sides = {L=1, R=1, U=1},
},
{false, true, true, false}) -- TA2/TA3

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -161,7 +161,6 @@ local tubing = {
local meta = minetest.get_meta(pos)
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
local inv = M(pos):get_inventory()
--CRD(pos).State:start_if_standby(pos) -- would need power!
return techage.put_items(inv, "src", stack)
end
end,
@ -217,6 +216,7 @@ local node_name_ta2, node_name_ta3, node_name_ta4 =
sounds = default.node_sound_wood_defaults(),
num_items = {0,1,2,4},
power_consumption = {0,3,4,5},
tube_sides = {L=1, R=1, U=1},
})
minetest.register_craft({

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -247,6 +247,7 @@ local node_name_ta2, node_name_ta3, node_name_ta4 =
sounds = default.node_sound_wood_defaults(),
num_items = {0,1,2,4},
power_consumption = {0,4,6,9},
tube_sides = {L=1, R=1, U=1},
})
minetest.register_craft({
@ -258,23 +259,23 @@ minetest.register_craft({
},
})
minetest.register_craft({
output = node_name_ta3,
recipe = {
{"", "default:mese_crystal", ""},
{"", node_name_ta2, ""},
{"", "techage:vacuum_tube", ""},
},
})
--minetest.register_craft({
-- output = node_name_ta3,
-- recipe = {
-- {"", "default:mese_crystal", ""},
-- {"", node_name_ta2, ""},
-- {"", "techage:vacuum_tube", ""},
-- },
--})
minetest.register_craft({
output = node_name_ta4,
recipe = {
{"", "default:mese_crystal", ""},
{"", node_name_ta3, ""},
{"", "techage:ta4_wlanchip", ""},
},
})
--minetest.register_craft({
-- output = node_name_ta4,
-- recipe = {
-- {"", "default:mese_crystal", ""},
-- {"", node_name_ta3, ""},
-- {"", "techage:ta4_wlanchip", ""},
-- },
--})
if minetest.global_exists("unified_inventory") then
unified_inventory.register_craft_type("grinding", {

View File

@ -290,6 +290,7 @@ local node_name_ta2, node_name_ta3, node_name_ta4 =
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
num_items = {0,2,6,12},
tube_sides = {L=1, R=1},
})
minetest.register_craft({

View File

@ -3,12 +3,12 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
TA2/TA3/TA4 Power Test Source
TA2/TA3 Power Test Source
]]--
@ -18,26 +18,17 @@ local M = minetest.get_meta
local S = techage.S
local Axle = techage.Axle
local Pipe = techage.SteamPipe
--local Pipe = techage.SteamPipe
local Cable = techage.ElectricCable
local power = techage.power
local networks = techage.networks
local power = networks.power
local control = networks.control
local STANDBY_TICKS = 4
local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 2
local PWR_CAPA = 100
local PWR_PERF = 100
local function formspec(self, pos, nvm)
return "size[4,4]"..
"box[0,-0.1;3.8,0.5;#c6e8ff]"..
"label[1,-0.1;"..minetest.colorize( "#000000", S("Power Source")).."]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
power.formspec_label_bar(pos, 0, 0.8, S("power"), PWR_CAPA, nvm.provided)..
"image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
"tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]"
return techage.generator_formspec(self, pos, nvm, S("Power Source"), nvm.provided, PWR_PERF)
end
-- Axles texture animation
@ -47,44 +38,36 @@ local function switch_axles(pos, on)
end
local function start_node2(pos, nvm, state)
nvm.generating = true
nvm.running = true
nvm.provided = 0
local outdir = M(pos):get_int("outdir")
power.generator_start(pos, Axle, CYCLE_TIME, outdir)
switch_axles(pos, true)
power.start_storage_calc(pos, Axle, outdir)
end
local function stop_node2(pos, nvm, state)
nvm.generating = false
nvm.running = false
nvm.provided = 0
nvm.load = 0
local outdir = M(pos):get_int("outdir")
power.generator_stop(pos, Axle, outdir)
switch_axles(pos, false)
power.start_storage_calc(pos, Axle, outdir)
end
local function start_node3(pos, nvm, state)
nvm.generating = true
local outdir = M(pos):get_int("outdir")
power.generator_start(pos, Pipe, CYCLE_TIME, outdir)
local meta = M(pos)
nvm.running = true
nvm.provided = 0
techage.evaluate_charge_termination(nvm, meta)
local outdir = meta:get_int("outdir")
power.start_storage_calc(pos, Cable, outdir)
end
local function stop_node3(pos, nvm, state)
nvm.generating = false
nvm.running = false
nvm.provided = 0
local outdir = M(pos):get_int("outdir")
power.generator_stop(pos, Pipe, outdir)
end
local function start_node4(pos, nvm, state)
nvm.generating = true
local outdir = M(pos):get_int("outdir")
power.generator_start(pos, Cable, CYCLE_TIME, outdir)
end
local function stop_node4(pos, nvm, state)
nvm.generating = false
nvm.provided = 0
local outdir = M(pos):get_int("outdir")
power.generator_stop(pos, Cable, outdir)
power.start_storage_calc(pos, Cable, outdir)
end
local State2 = techage.NodeStates:new({
@ -97,7 +80,7 @@ local State2 = techage.NodeStates:new({
})
local State3 = techage.NodeStates:new({
node_name_passive = "techage:t3_source",
node_name_passive = "techage:t4_source",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
formspec_func = formspec,
@ -105,44 +88,32 @@ local State3 = techage.NodeStates:new({
stop_node = stop_node3,
})
local State4 = techage.NodeStates:new({
node_name_passive = "techage:t4_source",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
formspec_func = formspec,
start_node = start_node4,
stop_node = stop_node4,
})
local function node_timer2(pos, elapsed)
--print("node_timer2")
local meta = M(pos)
local nvm = techage.get_nvm(pos)
local outdir = M(pos):get_int("outdir")
nvm.provided = power.generator_alive(pos, Axle, CYCLE_TIME, outdir)
local outdir = meta:get_int("outdir")
local tp1 = tonumber(meta:get_string("termpoint1"))
local tp2 = tonumber(meta:get_string("termpoint2"))
nvm.provided = power.provide_power(pos, Axle, outdir, PWR_PERF, tp1, tp2)
nvm.load = power.get_storage_load(pos, Axle, outdir, PWR_PERF)
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec(State2, pos, nvm))
meta:set_string("formspec", formspec(State2, pos, nvm))
end
return true
end
local function node_timer3(pos, elapsed)
--print("node_timer3")
local nvm = techage.get_nvm(pos)
local outdir = M(pos):get_int("outdir")
nvm.provided = power.generator_alive(pos, Pipe, CYCLE_TIME, outdir)
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec(State3, pos, nvm))
end
return true
end
local function node_timer4(pos, elapsed)
--print("node_timer4")
local meta = M(pos)
local nvm = techage.get_nvm(pos)
local outdir = M(pos):get_int("outdir")
nvm.provided = power.generator_alive(pos, Cable, CYCLE_TIME, outdir)
local tp1 = tonumber(meta:get_string("termpoint1"))
local tp2 = tonumber(meta:get_string("termpoint2"))
nvm.provided = power.provide_power(pos, Cable, outdir, PWR_PERF, tp1, tp2)
nvm.load = power.get_storage_load(pos, Cable, outdir, PWR_PERF)
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec(State4, pos, nvm))
meta:set_string("formspec", formspec(State3, pos, nvm))
end
return true
end
@ -165,15 +136,6 @@ local function on_receive_fields3(pos, formname, fields, player)
M(pos):set_string("formspec", formspec(State3, pos, nvm))
end
local function on_receive_fields4(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
end
local nvm = techage.get_nvm(pos)
State4:state_button_event(pos, nvm, fields)
M(pos):set_string("formspec", formspec(State4, pos, nvm))
end
local function on_rightclick2(pos, node, clicker)
techage.set_activeformspec(pos, clicker)
local nvm = techage.get_nvm(pos)
@ -186,12 +148,6 @@ local function on_rightclick3(pos, node, clicker)
M(pos):set_string("formspec", formspec(State3, pos, nvm))
end
local function on_rightclick4(pos, node, clicker)
techage.set_activeformspec(pos, clicker)
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(State4, pos, nvm))
end
local function after_place_node2(pos)
local nvm = techage.get_nvm(pos)
State2:node_init(pos, nvm, "")
@ -202,17 +158,10 @@ end
local function after_place_node3(pos)
local nvm = techage.get_nvm(pos)
State3:node_init(pos, nvm, "")
local number = techage.add_node(pos, "techage:t4_source")
State3:node_init(pos, nvm, number)
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
M(pos):set_string("formspec", formspec(State3, pos, nvm))
Pipe:after_place_node(pos)
end
local function after_place_node4(pos)
local nvm = techage.get_nvm(pos)
State4:node_init(pos, nvm, "")
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
M(pos):set_string("formspec", formspec(State4, pos, nvm))
Cable:after_place_node(pos)
end
@ -222,44 +171,17 @@ local function after_dig_node2(pos, oldnode)
end
local function after_dig_node3(pos, oldnode)
Pipe:after_dig_node(pos)
techage.del_mem(pos)
end
local function after_dig_node4(pos, oldnode)
Cable:after_dig_node(pos)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
local function get_generator_data(pos, outdir, tlib2)
local nvm = techage.get_nvm(pos)
if nvm.running then
return {level = (nvm.load or 0) / PWR_PERF, perf = PWR_PERF, capa = PWR_PERF * 2}
end
end
local net_def2 = {
axle = {
sides = {R = 1},
ntype = "gen1",
nominal = PWR_CAPA,
},
}
local net_def3 = {
pipe1 = {
sides = {R = 1},
ntype = "gen1",
nominal = PWR_CAPA,
},
}
local net_def4 = {
ele1 = {
sides = {R = 1},
ntype = "gen1",
nominal = PWR_CAPA,
},
}
minetest.register_node("techage:t2_source", {
description = S("Axle Power Source"),
tiles = {
@ -280,32 +202,7 @@ minetest.register_node("techage:t2_source", {
on_timer = node_timer2,
after_place_node = after_place_node2,
after_dig_node = after_dig_node2,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def2,
})
minetest.register_node("techage:t3_source", {
description = S("Steam Power Source"),
tiles = {
-- up, down, right, left, back, front
"techage_filling_ta3.png^techage_frame_ta3_top.png",
"techage_filling_ta3.png^techage_frame_ta3.png",
"techage_filling_ta3.png^techage_steam_hole.png^techage_frame_ta3.png",
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_source.png",
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_source.png",
"techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_source.png",
},
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
on_rotate = screwdriver.disallow,
is_ground_content = false,
on_receive_fields = on_receive_fields3,
on_rightclick = on_rightclick3,
on_timer = node_timer3,
after_place_node = after_place_node3,
after_dig_node = after_dig_node3,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def3,
get_generator_data = get_generator_data,
})
minetest.register_node("techage:t4_source", {
@ -323,15 +220,47 @@ minetest.register_node("techage:t4_source", {
groups = {cracky=2, crumbly=2, choppy=2},
on_rotate = screwdriver.disallow,
is_ground_content = false,
on_receive_fields = on_receive_fields4,
on_rightclick = on_rightclick4,
on_timer = node_timer4,
after_place_node = after_place_node4,
after_dig_node = after_dig_node4,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def4,
on_receive_fields = on_receive_fields3,
on_rightclick = on_rightclick3,
on_timer = node_timer3,
after_place_node = after_place_node3,
after_dig_node = after_dig_node3,
get_generator_data = get_generator_data,
ta3_formspec = techage.generator_settings("ta3", PWR_PERF),
})
Axle:add_secondary_node_names({"techage:t2_source"})
--Pipe:add_secondary_node_names({"techage:t3_source"})
Cable:add_secondary_node_names({"techage:t4_source"})
power.register_nodes({"techage:t2_source"}, Axle, "gen", {"R"})
power.register_nodes({"techage:t4_source"}, Cable, "gen", {"R"})
techage.register_node({"techage:t4_source"}, {
on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "delivered" then
return nvm.provided or 0
else
return State3:on_receive_message(pos, topic, payload)
end
end,
})
control.register_nodes({"techage:t4_source"}, {
on_receive = function(pos, tlib2, topic, payload)
end,
on_request = function(pos, tlib2, topic)
if topic == "info" then
local nvm = techage.get_nvm(pos)
local meta = M(pos)
return {
type = S("Ele Power Source"),
number = meta:get_string("node_number") or "",
running = nvm.running or false,
available = PWR_PERF,
provided = nvm.provided or 0,
termpoint = meta:get_string("termpoint"),
}
end
return false
end,
}
)

View File

@ -26,7 +26,7 @@ local techage_use_sqlite = minetest.settings:get_bool('techage_use_sqlite', fals
local string_split = string.split
local NodeDef = techage.NodeDef
local Tube = techage.Tube
local is_cart_available = minecart.is_cart_available
local is_cart_available = minecart.is_nodecart_available
-------------------------------------------------------------------
-- Database
@ -164,6 +164,19 @@ local function is_air_like(name)
return false
end
techage.SystemTime = 0
minetest.register_globalstep(function(dtime)
techage.SystemTime = techage.SystemTime + dtime
end)
-- used by TA1 hammer: dug_node[player_name] = pos
techage.dug_node = {}
minetest.register_on_dignode(function(pos, oldnode, digger)
if not digger then return end
-- store pos for tools without own 'register_on_dignode'
techage.dug_node[digger:get_player_name()] = pos
end)
-------------------------------------------------------------------
-- API helper functions
-------------------------------------------------------------------

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -17,7 +17,7 @@ local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local liquid = networks.liquid
local ValidOilFuels = techage.firebox.ValidOilFuels
local Burntime = techage.firebox.Burntime
@ -28,11 +28,12 @@ local BLOCKING_TIME = 0.3 -- 300ms
techage.fuel.CAPACITY = CAPACITY
-- fuel burning categories (better than...)
techage.fuel.BT_BITUMEN = 4
techage.fuel.BT_OIL = 3
techage.fuel.BT_FUELOIL = 2
techage.fuel.BT_NAPHTHA = 1
-- fuel burning categories (equal or better than...)
techage.fuel.BT_BITUMEN = 5
techage.fuel.BT_OIL = 4
techage.fuel.BT_FUELOIL = 3
techage.fuel.BT_NAPHTHA = 2
techage.fuel.BT_GASOLINE = 1
function techage.fuel.fuel_container(x, y, nvm)
@ -41,7 +42,7 @@ function techage.fuel.fuel_container(x, y, nvm)
itemname = nvm.liquid.name.." "..nvm.liquid.amount
end
local fuel_percent = 0
if nvm.running then
if nvm.running or techage.is_running(nvm) then
fuel_percent = ((nvm.burn_cycles or 1) * 100) / (nvm.burn_cycles_total or 1)
end
return "container["..x..","..y.."]"..
@ -95,6 +96,7 @@ function techage.fuel.burntime(name)
return 0.01 -- not zero !
end
-- equal or better than the given category (see 'techage.fuel.BT_BITUMEN,...')
function techage.fuel.valid_fuel(name, category)
return ValidOilFuels[name] and ValidOilFuels[name] <= category
end
@ -109,7 +111,7 @@ function techage.fuel.on_punch(pos, node, puncher, pointed_thing)
local wielded_item = puncher:get_wielded_item():get_name()
local item_count = puncher:get_wielded_item():get_count()
local new_item = liquid.fill_on_punch(nvm, wielded_item, item_count, puncher)
local new_item = techage.liquid.fill_on_punch(nvm, wielded_item, item_count, puncher)
if new_item then
puncher:set_wielded_item(new_item)
M(pos):set_string("formspec", techage.fuel.formspec(pos, nvm))
@ -117,11 +119,11 @@ function techage.fuel.on_punch(pos, node, puncher, pointed_thing)
return
end
local ldef = liquid.get_liquid_def(wielded_item)
local ldef = techage.liquid.get_liquid_def(wielded_item)
if ldef and ValidOilFuels[ldef.inv_item] then
local lqd = (minetest.registered_nodes[node.name] or {}).liquid
if not lqd.fuel_cat or ValidOilFuels[ldef.inv_item] <= lqd.fuel_cat then
local new_item = liquid.empty_on_punch(pos, nvm, wielded_item, item_count)
local new_item = techage.liquid.empty_on_punch(pos, nvm, wielded_item, item_count)
if new_item then
puncher:set_wielded_item(new_item)
M(pos):set_string("formspec", techage.fuel.formspec(pos, nvm))
@ -153,4 +155,43 @@ function techage.fuel.get_fuel_amount(nvm)
return nvm.liquid.amount
end
return 0
end
function techage.fuel.get_liquid_table(valid_fuel, capacity, start_firebox)
return {
capa = capacity,
fuel_cat = valid_fuel,
peek = function(pos)
local nvm = techage.get_nvm(pos)
return liquid.srv_peek(nvm)
end,
put = function(pos, indir, name, amount)
if techage.fuel.valid_fuel(name, valid_fuel) then
local nvm = techage.get_nvm(pos)
local res = liquid.srv_put(nvm, name, amount, capacity)
start_firebox(pos, nvm)
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", techage.fuel.formspec(nvm))
end
return res
end
return amount
end,
take = function(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
amount, name = liquid.srv_take(nvm, name, amount)
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", techage.fuel.formspec(nvm))
end
return amount, name
end,
untake = function(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
local leftover = liquid.srv_put(nvm, name, amount, capacity)
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", techage.fuel.formspec(nvm))
end
return leftover
end
}
end

25
basis/legacy.lua Normal file
View File

@ -0,0 +1,25 @@
--[[
TechAge
=======
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
For the transition from v0.26 to v1.0
]]--
function techage.register_node_for_v1_transition(nodenames, on_node_load)
minetest.register_lbm({
label = "[TechAge] V1 transition",
name = nodenames[1].."transition",
nodenames = nodenames,
run_at_every_load = false,
action = function(pos, node)
on_node_load(pos, node)
end
})
end

View File

@ -15,6 +15,7 @@
-- for lazy programmers
local P = minetest.string_to_pos
local M = minetest.get_meta
local S = techage.S
-- Input data to generate the Param2ToDir table
local Input = {
@ -336,3 +337,9 @@ function techage.question_mark_help(width, tooltip)
"tooltip["..x..",-0.1;0.5,0.5;"..tooltip..";#0C3D32;#FFFFFF]"
end
function techage.wrench_tooltip(x, y)
local tooltip = S("Block has an\nadditional wrench menu")
return "label["..x..","..y..";"..minetest.colorize("#000000", minetest.formspec_escape("[?]")).."]"..
"tooltip["..x..","..y..";0.5,0.5;"..tooltip..";#0C3D32;#FFFFFF]"
end

View File

@ -1,362 +0,0 @@
--[[
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
Networks - the connection of tubelib2 tube/pipe/cable lines to networks
]]--
local S2P = minetest.string_to_pos
local P2S = minetest.pos_to_string
local M = minetest.get_meta
local N = techage.get_node_lvm
local S = techage.S
local hex = function(val) return string.format("%x", val) end
local Networks = {} -- cache for networks
techage.networks = {} -- name space
local MAX_NUM_NODES = 1000
local BEST_BEFORE = 5 * 60 -- 5 minutes
local Route = {} -- Used to determine the already passed nodes while walking
local NumNodes = 0
local DirToSide = {"B", "R", "F", "L", "D", "U"}
local Sides = {B = true, R = true, F = true, L = true, D = true, U = true}
local SideToDir = {B=1, R=2, F=3, L=4, D=5, U=6}
local Flip = {[0]=0,3,4,1,2,6,5} -- 180 degree turn
local function error(pos, msg)
minetest.log("error", "[techage] "..msg.." at "..P2S(pos).." "..N(pos).name)
end
local function count_nodes(ntype, nodes)
local num = 0
for _,pos in ipairs(nodes or {}) do
num = num + 1
end
return ntype.."="..num
end
local function output(network, valid)
local tbl = {}
for ntype,table in pairs(network) do
if type(table) == "table" then
tbl[#tbl+1] = count_nodes(ntype, table)
end
end
print("Network ("..valid.."): "..table.concat(tbl, ", "))
end
local function debug(ntype)
local tbl = {}
for netID,netw in pairs(Networks[ntype] or {}) do
if type(netw) == "table" then
tbl[#tbl+1] = string.format("%X", netID)
end
end
return "Networks: "..table.concat(tbl, ", ")
end
local function hidden_node(pos, net_name)
local name = M(pos):get_string("techage_hidden_nodename")
local ndef = minetest.registered_nodes[name]
if ndef and ndef.networks then
return ndef.networks[net_name] or {}
end
return {}
end
-- return the node definition local networks table
local function net_def(pos, net_name)
local ndef = minetest.registered_nodes[techage.get_node_lvm(pos).name]
if ndef and ndef.networks then
return ndef.networks[net_name] or {}
else -- hidden junction
return hidden_node(pos, net_name)
end
end
local function net_def2(pos, node_name, net_name)
local ndef = minetest.registered_nodes[node_name]
if ndef and ndef.networks then
return ndef.networks[net_name] or {}
else -- hidden junction
return hidden_node(pos, net_name)
end
end
local function connected(tlib2, pos, dir)
local param2, npos = tlib2:get_primary_node_param2(pos, dir)
if param2 then
local d1, d2, num = tlib2:decode_param2(npos, param2)
if not num then return end
return Flip[dir] == d1 or Flip[dir] == d2
end
-- secondary nodes allowed?
if tlib2.force_to_use_tubes then
return tlib2:is_special_node(pos, dir)
else
return tlib2:is_secondary_node(pos, dir)
end
return false
end
-- Calculate the node outdir based on node.param2 and nominal dir (according to side)
local function dir_to_outdir(dir, param2)
if dir < 5 then
return ((dir + param2 - 1) % 4) + 1
end
return dir
end
local function indir_to_dir(indir, param2)
if indir < 5 then
return ((indir - param2 + 5) % 4) + 1
end
return Flip[indir]
end
local function outdir_to_dir(outdir, param2)
if outdir < 5 then
return ((outdir - param2 + 3) % 4) + 1
end
return outdir
end
local function side_to_outdir(pos, side)
return dir_to_outdir(SideToDir[side], techage.get_node_lvm(pos).param2)
end
-- Get tlib2 connection dirs as table
-- used e.g. for the connection walk
local function get_node_connections(pos, net_name)
local val = M(pos):get_int(net_name.."_conn")
local tbl = {}
if val % 0x40 >= 0x20 then tbl[#tbl+1] = 1 end
if val % 0x20 >= 0x10 then tbl[#tbl+1] = 2 end
if val % 0x10 >= 0x08 then tbl[#tbl+1] = 3 end
if val % 0x08 >= 0x04 then tbl[#tbl+1] = 4 end
if val % 0x04 >= 0x02 then tbl[#tbl+1] = 5 end
if val % 0x02 >= 0x01 then tbl[#tbl+1] = 6 end
return tbl
end
-- store all node sides with tube connections as nodemeta
local function node_connections(pos, tlib2)
local node = techage.get_node_lvm(pos)
local val = 0
local ndef = net_def2(pos, node.name, tlib2.tube_type)
local sides = ndef.sides or ndef.get_sides and ndef.get_sides(pos, node)
if sides then
for dir = 1,6 do
val = val * 2
local side = DirToSide[outdir_to_dir(dir, node.param2)]
if sides[side] then
if connected(tlib2, pos, dir) then
--techage.mark_side("singleplayer", pos, dir, "node_connections", "", 1)--------------------
val = val + 1
end
end
end
M(pos):set_int(tlib2.tube_type.."_conn", val)
else
--error(pos, "sides missing")
end
end
local function pos_already_reached(pos)
local key = minetest.hash_node_position(pos)
if not Route[key] and NumNodes < MAX_NUM_NODES then
Route[key] = true
NumNodes = NumNodes + 1
return false
end
return true
end
-- check if the given pipe dir into the node is valid
local function valid_indir(pos, indir, node, net_name)
local ndef = net_def2(pos, node.name, net_name)
local sides = ndef.sides or ndef.get_sides and ndef.get_sides(pos, node)
local side = DirToSide[indir_to_dir(indir, node.param2)]
if not sides or sides and not sides[side] then return false end
return true
end
local function is_junction(pos, name, tube_type)
local ndef = net_def2(pos, name, tube_type)
-- ntype can be a string or an array of strings or nil
if ndef.ntype == "junc" then
return true
end
if type(ndef.ntype) == "table" then
for _,ntype in ipairs(ndef.ntype) do
if ntype == "junc" then
return true
end
end
end
return false
end
-- do the walk through the tubelib2 network
-- indir is the direction which should not be covered by the walk
-- (coming from there)
-- if outdirs is given, only this dirs are used
local function connection_walk(pos, outdirs, indir, node, tlib2, clbk)
if clbk then clbk(pos, indir, node) end
--techage.mark_position("singleplayer", pos, "walk", "", 1)
--print("connection_walk", node.name, outdirs or is_junction(pos, node.name, tlib2.tube_type))
if outdirs or is_junction(pos, node.name, tlib2.tube_type) then
for _,outdir in pairs(outdirs or get_node_connections(pos, tlib2.tube_type)) do
--techage.mark_side("singleplayer", pos, outdir, "connection_walk", "", 3)--------------------
--print("get_node_connections", node.name, outdir)
local pos2, indir2 = tlib2:get_connected_node_pos(pos, outdir)
local node = techage.get_node_lvm(pos2)
if pos2 and not pos_already_reached(pos2) and valid_indir(pos2, indir2, node, tlib2.tube_type) then
connection_walk(pos2, nil, indir2, node, tlib2, clbk)
end
end
end
end
local function collect_network_nodes(pos, outdir, tlib2)
Route = {}
NumNodes = 0
pos_already_reached(pos)
local netw = {}
local node = techage.get_node_lvm(pos)
local net_name = tlib2.tube_type
-- outdir corresponds to the indir coming from
connection_walk(pos, outdir and {outdir}, nil, node, tlib2, function(pos, indir, node)
local ndef = net_def2(pos, node.name, net_name)
-- ntype can be a string or an array of strings or nil
local ntypes = ndef.ntype or {}
if type(ntypes) == "string" then
ntypes = {ntypes}
end
for _,ntype in ipairs(ntypes) do
if not netw[ntype] then netw[ntype] = {} end
netw[ntype][#netw[ntype] + 1] = {pos = pos, indir = indir, nominal = ndef.nominal, regenerative = ndef.regenerative}
end
end)
netw.best_before = minetest.get_gametime() + BEST_BEFORE
netw.num_nodes = NumNodes
return netw
end
-- keep data base small and valid
-- needed for networks without scheduler
local function remove_outdated_networks()
local to_be_deleted = {}
local t = minetest.get_gametime()
for net_name,tbl in pairs(Networks) do
for netID,network in pairs(tbl) do
local valid = (network.best_before or 0) - t
--output(network, valid)
if valid < 0 then
to_be_deleted[#to_be_deleted+1] = {net_name, netID}
end
end
end
for _,item in ipairs(to_be_deleted) do
local net_name, netID = unpack(item)
Networks[net_name][netID] = nil
end
minetest.after(60, remove_outdated_networks)
end
minetest.after(60, remove_outdated_networks)
--
-- API Functions
--
-- Table fo a 180 degree turn
techage.networks.Flip = Flip
-- techage.networks.net_def(pos, net_name)
techage.networks.net_def = net_def
techage.networks.AllSides = Sides -- table for all 6 node sides
-- techage.networks.side_to_outdir(pos, side)
techage.networks.side_to_outdir = side_to_outdir
-- techage.networks.node_connections(pos, tlib2)
techage.networks.node_connections = node_connections
-- techage.networks.collect_network_nodes(pos, outdir, tlib2)
techage.networks.collect_network_nodes = collect_network_nodes
function techage.networks.connection_walk(pos, outdir, tlib2, clbk)
Route = {}
NumNodes = 0
pos_already_reached(pos) -- don't consider the start pos
local node = techage.get_node_lvm(pos)
connection_walk(pos, outdir and {outdir}, Flip[outdir], node, tlib2, clbk)
return NumNodes
end
-- return network without maintainting the "alive" data
function techage.networks.peek_network(tube_type, netID)
--print("peek_network", debug(tube_type))
return Networks[tube_type] and Networks[tube_type][netID]
end
function techage.networks.set_network(tube_type, netID, network)
if netID then
if not Networks[tube_type] then
Networks[tube_type] = {}
end
Networks[tube_type][netID] = network
Networks[tube_type][netID].best_before = minetest.get_gametime() + BEST_BEFORE
end
end
--
-- Power API
--
function techage.networks.has_network(tube_type, netID)
return Networks[tube_type] and Networks[tube_type][netID]
end
function techage.networks.build_network(pos, outdir, tlib2, netID)
local netw = collect_network_nodes(pos, outdir, tlib2)
Networks[tlib2.tube_type] = Networks[tlib2.tube_type] or {}
Networks[tlib2.tube_type][netID] = netw
netw.alive = 3
-- sort generating1 nodes, so that regenerative ones will be used first
if netw.gen1 then
table.sort(netw.gen1, function(a,b) return a.regenerative and not b.regenerative end)
end
techage.schedule.start(tlib2.tube_type, netID)
end
function techage.networks.get_network(tube_type, netID)
--print("get_network", string.format("%X", netID), debug(tube_type))
local netw = Networks[tube_type] and Networks[tube_type][netID]
if netw then
netw.alive = 3 -- monitored by scheduler (power)
netw.best_before = minetest.get_gametime() + BEST_BEFORE -- monitored by networks (liquids)
return netw
end
end
function techage.networks.delete_network(tube_type, netID)
if Networks[tube_type] and Networks[tube_type][netID] then
Networks[tube_type][netID] = nil
end
end
-- Get node tubelib2 connections as table of outdirs
-- techage.networks.get_node_connections(pos, net_name)
techage.networks.get_node_connections = get_node_connections
techage.networks.MAX_NUM_NODES = MAX_NUM_NODES

View File

@ -67,7 +67,7 @@ local N = techage.get_node_lvm
--
techage.RUNNING = 1 -- in normal operation/turned on
techage.BLOCKED = 2 -- a pushing node is blocked due to a full destination inventory
techage.BLOCKED = 2 -- a pushing node is blocked due to a full destination inventory
techage.STANDBY = 3 -- nothing to do (e.g. no input items), or node (world) not loaded
techage.NOPOWER = 4 -- only for power consuming nodes, no operation
techage.FAULT = 5 -- any fault state (e.g. wrong source items), which can be fixed by the player
@ -155,14 +155,13 @@ end
-- consumes power
function techage.needs_power(nvm)
local state = nvm.techage_state or STOPPED
-- "blocked" must need power, otherwise it could happen, that the node
-- is not in the power network anymore and gets not started if
-- power is turned off and on again.
return state < STANDBY or state == NOPOWER
return state == RUNNING or state == NOPOWER
end
-- consumes power
function techage.needs_power2(state)
return state < STANDBY or state == NOPOWER
state = state or STOPPED
return state == RUNNING or state == NOPOWER
end
function techage.get_state_string(nvm)

View File

@ -19,6 +19,8 @@ local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local S2P = minetest.string_to_pos
local MP = minetest.get_modpath("minecart")
local Tube = techage.Tube
local function on_rightclick(pos, node, clicker)
if clicker and clicker:is_player() then
if M(pos):get_int("userID") == 0 then
@ -159,6 +161,8 @@ techage.register_node({"techage:chest_cart"}, {
end,
})
Tube:set_valid_sides("techage:chest_cart", {"L", "R", "F", "B"})
minetest.register_craft({
output = "techage:chest_cart",
recipe = {

View File

@ -18,9 +18,9 @@ local S = techage.S
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local S2P = minetest.string_to_pos
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local MP = minetest.get_modpath("minecart")
local liquid = networks.liquid
local CAPACITY = 100
local function on_rightclick(pos, node, clicker)
@ -30,7 +30,7 @@ local function on_rightclick(pos, node, clicker)
else
local nvm = techage.get_nvm(pos)
techage.set_activeformspec(pos, clicker)
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
minetest.get_node_timer(pos):start(2)
end
end
@ -39,50 +39,48 @@ end
local function node_timer(pos, elapsed)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
return true
end
return false
end
local function peek_liquid(pos)
local nvm = techage.get_nvm(pos)
return liquid.srv_peek(nvm)
end
local function take_liquid(pos, indir, name, amount)
amount, name = liquid.srv_take(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
amount, name = liquid.srv_take(nvm, name, amount)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
end
return amount, name
end
local function untake_liquid(pos, indir, name, amount)
local leftover = liquid.srv_put(pos, indir, name, amount)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
end
return leftover
end
local function put_liquid(pos, indir, name, amount)
-- check if it is not powder
local ndef = minetest.registered_craftitems[name] or {}
if not ndef.groups or ndef.groups.powder ~= 1 then
local leftover = liquid.srv_put(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
local leftover = liquid.srv_put(nvm, name, amount, CAPACITY)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
end
return leftover
end
return amount
end
local networks_def = {
pipe2 = {
sides = {U = 1}, -- Pipe connection side
ntype = "tank",
},
}
local function untake_liquid(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
local leftover = liquid.srv_put(nvm, name, amount, CAPACITY)
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
end
return leftover
end
minetest.register_node("techage:tank_cart", {
description = S("TA Tank Cart"),
@ -119,7 +117,7 @@ minetest.register_node("techage:tank_cart", {
after_place_node = function(pos)
local nvm = techage.get_nvm(pos)
nvm.liquid = nvm.liquid or {}
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
end,
set_cargo = function(pos, data)
@ -135,26 +133,24 @@ minetest.register_node("techage:tank_cart", {
end,
has_cargo = function(pos)
return not liquid.is_empty(pos)
return not techage.liquid.is_empty(pos)
end,
on_timer = node_timer,
liquid = {
capa = CAPACITY,
peek = liquid.srv_peek,
put = put_liquid,
take = take_liquid,
untake = untake_liquid,
},
networks = networks_def,
on_rightclick = on_rightclick,
})
techage.register_node({"techage:tank_cart"}, liquid.recv_message)
Pipe:add_secondary_node_names({"techage:tank_cart"})
techage.register_node({"techage:tank_cart"}, techage.liquid.recv_message)
liquid.register_nodes({"techage:tank_cart"},
Pipe, "tank", {"U"}, {
capa = CAPACITY,
peek = peek_liquid,
put = put_liquid,
take = take_liquid,
untake = untake_liquid,
}
)
minecart.register_cart_entity("techage:tank_cart_entity", "techage:tank_cart", "tank", {
initial_properties = {

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -17,8 +17,7 @@ local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local Pipe = techage.LiquidPipe
local networks = techage.networks
local liquid = techage.liquid
local liquid = networks.liquid
local recipes = techage.recipes
local Liquids = {} -- {hash(pos) = {name = outdir},...}
@ -27,26 +26,6 @@ local STANDBY_TICKS = 2
local COUNTDOWN_TICKS = 3
local CYCLE_TIME = 10
-- to mark the pump source and destinstion node
local DebugCache = {}
local function set_starter_name(pos, clicker)
local key = minetest.hash_node_position(pos)
DebugCache[key] = {starter = clicker:get_player_name(), count = 10}
end
local function get_starter_name(pos)
local key = minetest.hash_node_position(pos)
local def = DebugCache[key]
if def then
def.count = (def.count or 0) - 1
if def.count > 0 then
return def.starter
end
DebugCache[key] = nil
end
end
local function formspec(self, pos, nvm)
return "size[6,3.6]"..
default.gui_bg..
@ -67,7 +46,7 @@ local function get_liquids(pos)
-- determine the available input liquids
local tbl = {}
for outdir = 1,4 do
local name, num = liquid.peek(pos, outdir)
local name, num = liquid.peek(pos, Pipe, outdir)
if name then
tbl[name] = outdir
end
@ -87,7 +66,7 @@ local function reload_liquids(pos)
-- determine the available input liquids
local tbl = {}
for outdir = 1,4 do
local name, num = liquid.peek(pos, outdir)
local name, num = liquid.peek(pos, Pipe, outdir)
if name then
tbl[name] = outdir
end
@ -155,7 +134,7 @@ local State = techage.NodeStates:new({
local function untake(pos, taken)
for _,item in pairs(taken) do
liquid.untake(pos, item.outdir, item.name, item.num)
liquid.untake(pos, Pipe, item.outdir, item.name, item.num)
end
end
@ -199,8 +178,10 @@ local function dosing(pos, nvm, elapsed)
end
end
-- inputs
local starter = get_starter_name(pos)
local taken = {}
local mem = techage.get_mem(pos)
mem.dbg_cycles = (mem.dbg_cycles or 0) - 1
for _,item in pairs(recipe.input) do
if item.name ~= "" then
local outdir = liquids[item.name] or reload_liquids(pos)[item.name]
@ -210,7 +191,7 @@ local function dosing(pos, nvm, elapsed)
untake(pos, taken)
return
end
local num = liquid.take(pos, outdir, item.name, item.num, starter)
local num = liquid.take(pos, Pipe, outdir, item.name, item.num, mem.dbg_cycles > 0)
if num < item.num then
taken[#taken + 1] = {outdir = outdir, name = item.name, num = num}
State:standby(pos, nvm)
@ -267,19 +248,12 @@ local function on_receive_fields(pos, formname, fields, player)
if not nvm.running then
recipes.on_receive_fields(pos, formname, fields, player)
end
set_starter_name(pos, player)
local mem = techage.get_mem(pos)
mem.dbg_cycles = 5
State:state_button_event(pos, nvm, fields)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
local nworks = {
pipe2 = {
sides = techage.networks.AllSides, -- Pipe connection sides
ntype = "pump",
},
}
minetest.register_node("techage:ta4_doser", {
description = S("TA4 Doser"),
tiles = {
@ -301,19 +275,17 @@ minetest.register_node("techage:ta4_doser", {
Pipe:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, dir, tlib2, node)
liquid.update_network(pos, dir)
liquid.update_network(pos, dir, tlib2, node)
del_liquids(pos)
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
techage.remove_node(pos, oldnode, oldmetadata)
Pipe:after_dig_node(pos)
liquid.after_dig_pump(pos)
techage.del_mem(pos)
end,
on_receive_fields = on_receive_fields,
on_rightclick = on_rightclick,
on_timer = node_timer,
networks = nworks,
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
@ -341,13 +313,12 @@ minetest.register_node("techage:ta4_doser_on", {
},
tubelib2_on_update2 = function(pos, dir, tlib2, node)
liquid.update_network(pos, dir)
liquid.update_network(pos, dir, tlib2, node)
del_liquids(pos)
end,
on_receive_fields = on_receive_fields,
on_rightclick = on_rightclick,
on_timer = node_timer,
networks = nworks,
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
@ -357,15 +328,14 @@ minetest.register_node("techage:ta4_doser_on", {
sounds = default.node_sound_metal_defaults(),
})
liquid.register_nodes({"techage:ta4_doser", "techage:ta4_doser_on"}, Pipe, "pump", nil, {})
techage.register_node({"techage:ta4_doser", "techage:ta4_doser_on"}, {
on_recv_message = function(pos, src, topic, payload)
return State:on_receive_message(pos, topic, payload)
end,
})
Pipe:add_secondary_node_names({"techage:ta4_doser", "techage:ta4_doser_on"})
if minetest.global_exists("unified_inventory") then
unified_inventory.register_craft_type("ta4_doser", {
description = S("TA4 Reactor"),

View File

@ -105,7 +105,6 @@ minetest.register_node("techage:ta4_liquid_filter_filler", {
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
liquid.after_dig_pump(pos)
techage.del_mem(pos)
end,
@ -134,7 +133,7 @@ minetest.register_node("techage:ta4_liquid_filter_filler", {
end
if math.random() < 0.5 then
local out_pos = {x=pos.x,y=pos.y-8,z=pos.z}
local leftover = liquid.put(out_pos, networks.side_to_outdir(out_pos, "R"), "techage:lye", 1)
local leftover = liquid.put(out_pos, Pipe, networks.side_to_outdir(out_pos, "R"), "techage:lye", 1)
if leftover > 0 then
return amount
end

View File

@ -15,8 +15,8 @@
local S = techage.S
local M = minetest.get_meta
local Pipe = techage.LiquidPipe
local networks = techage.networks
local liquid = techage.liquid
local Cable = techage.ElectricCable
local liquid = networks.liquid
minetest.register_node("techage:ta4_reactor_fillerpipe", {
description = S("TA4 Reactor Filler Pipe"),
@ -48,9 +48,9 @@ minetest.register_node("techage:ta4_reactor_fillerpipe", {
Pipe:after_place_node(pos1)
end
end,
tubelib2_on_update2 = function(pos, dir, tlib2, node)
liquid.update_network(pos)
end,
-- tubelib2_on_update2 = function(pos, dir, tlib2, node)
-- liquid.update_network(pos, dir, tlib2, node)
-- end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
end,
@ -63,13 +63,6 @@ minetest.register_node("techage:ta4_reactor_fillerpipe", {
groups = {cracky=2},
is_ground_content = false,
sounds = default.node_sound_metal_defaults(),
networks = {
pipe2 = {
sides = {U = 1}, -- Pipe connection sides
ntype = "tank",
},
},
})
local function stand_cmnd(pos, cmnd, payload)
@ -85,7 +78,7 @@ end
local function base_waste(pos, payload)
local pos2 = {x = pos.x, y = pos.y-3, z = pos.z}
local outdir = M(pos2):get_int("outdir")
return liquid.put(pos2, outdir, payload.name, payload.amount, payload.player_name)
return liquid.put(pos2, Pipe, outdir, payload.name, payload.amount, payload.player_name)
end
-- controlled by the doser
@ -117,6 +110,8 @@ techage.register_node({"techage:ta4_reactor_fillerpipe"}, {
end,
})
liquid.register_nodes({"techage:ta4_reactor_fillerpipe"}, Pipe, "tank", {"U"}, {})
local function formspec()
local title = S("TA4 Reactor")
return "size[8,6]"..
@ -176,8 +171,6 @@ minetest.register_node("techage:ta4_reactor", {
sounds = default.node_sound_metal_defaults(),
})
Pipe:add_secondary_node_names({"techage:ta4_reactor_fillerpipe"})
minetest.register_craft({
output = 'techage:ta4_reactor',
recipe = {

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -15,13 +15,12 @@
local S = techage.S
local M = minetest.get_meta
local Cable = techage.ElectricCable
local power = techage.power
local Pipe = techage.LiquidPipe
local networks = techage.networks
local liquid = techage.liquid
local power = networks.power
local liquid = networks.liquid
local PWR_NEEDED = 8
local CYCLE_TIME = 4
local CYCLE_TIME = 2
local function play_sound(pos)
local mem = techage.get_mem(pos)
@ -49,18 +48,18 @@ local function on_power(pos)
M(pos):set_string("infotext", S("on"))
play_sound(pos)
local nvm = techage.get_nvm(pos)
nvm.has_power = true
nvm.running = true
end
local function on_nopower(pos)
M(pos):set_string("infotext", S("no power"))
stop_sound(pos)
local nvm = techage.get_nvm(pos)
nvm.has_power = false
nvm.running = false
end
local function is_running(pos, nvm)
return nvm.has_power
return nvm.running
end
minetest.register_node("techage:ta4_reactor_stand", {
@ -103,21 +102,26 @@ minetest.register_node("techage:ta4_reactor_stand", {
Pipe:after_place_node(pos)
Cable:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, dir, tlib2, node)
if tlib2.tube_type == "ele1" then
power.update_network(pos, dir, tlib2)
else
liquid.update_network(pos, dir, tlib2)
end
end,
-- tubelib2_on_update2 = function(pos, dir, tlib2, node)
-- if tlib2.tube_type == "ele1" then
-- power.update_network(pos, dir, tlib2, node)
-- else
-- liquid.update_network(pos, dir, tlib2, node)
-- end
-- end,
on_timer = function(pos, elapsed)
power.consumer_alive(pos, Cable, CYCLE_TIME)
local nvm = techage.get_nvm(pos)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if not nvm.running and consumed == PWR_NEEDED then
on_power(pos)
elseif nvm.running and consumed < PWR_NEEDED then
on_nopower(pos)
end
return true
end,
after_dig_node = function(pos, oldnode)
Pipe:after_dig_node(pos)
Cable:after_dig_node(pos)
liquid.after_dig_pump(pos)
techage.del_mem(pos)
end,
@ -128,21 +132,6 @@ minetest.register_node("techage:ta4_reactor_stand", {
groups = {cracky=2},
is_ground_content = false,
sounds = default.node_sound_metal_defaults(),
networks = {
pipe2 = {
sides = {R=1},
ntype = "pump",
},
ele1 = {
sides = {L=1},
ntype = "con1",
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED,
is_running = is_running,
},
},
})
-- controlled by the fillerpipe
@ -150,21 +139,19 @@ techage.register_node({"techage:ta4_reactor_stand"}, {
on_transfer = function(pos, in_dir, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "power" then
return nvm.has_power or power.power_available(pos, Cable)
return nvm.running or power.power_available(pos, Cable)
elseif topic == "output" then
local outdir = M(pos):get_int("outdir")
return liquid.put(pos, outdir, payload.name, payload.amount, payload.player_name)
return liquid.put(pos, Pipe, outdir, payload.name, payload.amount, payload.player_name)
elseif topic == "can_start" then
return power.power_available(pos, Cable)
elseif topic == "start" then
nvm.has_power = false
power.consumer_start(pos, Cable, CYCLE_TIME)
nvm.running = false
minetest.get_node_timer(pos):start(CYCLE_TIME)
M(pos):set_string("infotext", "...")
return true
elseif topic == "stop" then
nvm.has_power = false
power.consumer_stop(pos, Cable)
stop_sound(pos)
minetest.get_node_timer(pos):stop()
M(pos):set_string("infotext", S("off"))
@ -195,9 +182,9 @@ minetest.register_node("techage:ta4_reactor_base", {
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
Pipe:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, dir, tlib2, node)
liquid.update_network(pos, dir, tlib2)
end,
-- tubelib2_on_update2 = function(pos, dir, tlib2, node)
-- liquid.update_network(pos, dir, tlib2, node)
-- end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
end,
@ -207,21 +194,11 @@ minetest.register_node("techage:ta4_reactor_base", {
groups = {cracky=2},
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
networks = {
pipe2 = {
sides = {R=1}, -- Pipe connection sides
ntype = "pump",
},
},
})
Pipe:add_secondary_node_names({
"techage:ta4_reactor_base",
"techage:ta4_reactor_stand",
})
Cable:add_secondary_node_names({"techage:ta4_reactor_stand"})
liquid.register_nodes({"techage:ta4_reactor_base"}, Pipe, "pump", {"R"}, {})
liquid.register_nodes({"techage:ta4_reactor_stand"}, Pipe, "pump", {"R"}, {})
power.register_nodes({"techage:ta4_reactor_stand"}, Cable, "con", {"L"})
minetest.register_craft({
output = 'techage:ta4_reactor_stand',

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -16,25 +16,17 @@
local M = minetest.get_meta
local S = techage.S
local Cable = techage.ElectricCable
local power = networks.power
local control = networks.control
local CYCLE_TIME = 2
local STANDBY_TICKS = 4
local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 2
local PWR_CAPA = 80
local Cable = techage.ElectricCable
local power = techage.power
local networks = techage.networks
local PWR_PERF = 80
local function formspec(self, pos, nvm)
return "size[4,4]"..
"box[0,-0.1;3.8,0.5;#c6e8ff]"..
"label[1,-0.1;"..minetest.colorize( "#000000", S("Generator")).."]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
power.formspec_label_bar(pos, 0, 0.8, S("power"), PWR_CAPA, nvm.provided)..
"image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
"tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]"
return techage.generator_formspec(self, pos, nvm, S("Generator"), nvm.provided, PWR_PERF)
end
local function transfer_turbine(pos, topic, payload)
@ -46,19 +38,25 @@ local function can_start(pos, nvm, state)
return (nvm.firebox_trigger or 0) > 0 -- by means of firebox
end
local function has_fire(nvm)
nvm.firebox_trigger = (nvm.firebox_trigger or 0) - 1
return nvm.firebox_trigger > 0
end
local function start_node(pos, nvm, state)
local outdir = M(pos):get_int("outdir")
power.generator_start(pos, Cable, CYCLE_TIME, outdir)
local meta = M(pos)
nvm.provided = 0
local outdir = meta:get_int("outdir")
transfer_turbine(pos, "start")
nvm.running = true
power.start_storage_calc(pos, Cable, outdir)
techage.evaluate_charge_termination(nvm, meta)
end
local function stop_node(pos, nvm, state)
local outdir = M(pos):get_int("outdir")
power.generator_stop(pos, Cable, outdir)
nvm.provided = 0
local outdir = M(pos):get_int("outdir")
transfer_turbine(pos, "stop")
nvm.running = false
power.start_storage_calc(pos, Cable, outdir)
end
local State = techage.NodeStates:new({
@ -75,14 +73,24 @@ local State = techage.NodeStates:new({
local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos)
nvm.firebox_trigger = (nvm.firebox_trigger or 0) - 1
if nvm.firebox_trigger <= 0 then
State:nopower(pos, nvm)
local running = techage.is_running(nvm)
local fire = has_fire(nvm)
if running and not fire then
State:standby(pos, nvm)
stop_node(pos, nvm, State)
transfer_turbine(pos, "stop")
else
local outdir = M(pos):get_int("outdir")
nvm.provided = power.generator_alive(pos, Cable, CYCLE_TIME, outdir)
elseif not running and fire then
State:start(pos, nvm)
-- start_node() is called implicit
elseif running then
local meta = M(pos)
local outdir = meta:get_int("outdir")
local tp1 = tonumber(meta:get_string("termpoint1"))
local tp2 = tonumber(meta:get_string("termpoint2"))
nvm.provided = power.provide_power(pos, Cable, outdir, PWR_PERF, tp1, tp2)
local val = power.get_storage_load(pos, Cable, outdir, PWR_PERF)
if val > 0 then
nvm.load = val
end
State:keep_running(pos, nvm, COUNTDOWN_TICKS)
end
if techage.is_activeformspec(pos) then
@ -119,18 +127,13 @@ local function after_dig_node(pos, oldnode)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
local function get_generator_data(pos, outdir, tlib2)
local nvm = techage.get_nvm(pos)
if techage.is_running(nvm) then
return {level = (nvm.load or 0) / PWR_PERF, perf = PWR_PERF, capa = PWR_PERF * 2}
end
end
local net_def = {
ele1 = {
sides = {R = 1},
ntype = "gen1",
nominal = PWR_CAPA,
},
}
minetest.register_node("techage:generator", {
description = S("TA3 Generator"),
tiles = {
@ -148,8 +151,8 @@ minetest.register_node("techage:generator", {
on_timer = node_timer,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
get_generator_data = get_generator_data,
ta3_formspec = techage.generator_settings("ta3", PWR_PERF),
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
@ -193,8 +196,8 @@ minetest.register_node("techage:generator_on", {
on_timer = node_timer,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
get_generator_data = get_generator_data,
ta3_formspec = techage.generator_settings("ta3", PWR_PERF),
drop = "",
paramtype2 = "facedir",
@ -205,7 +208,7 @@ minetest.register_node("techage:generator_on", {
sounds = default.node_sound_wood_defaults(),
})
Cable:add_secondary_node_names({"techage:generator", "techage:generator_on"})
power.register_nodes({"techage:generator", "techage:generator_on"}, Cable, "gen", {"R"})
-- controlled by the turbine
techage.register_node({"techage:generator", "techage:generator_on"}, {
@ -213,8 +216,8 @@ techage.register_node({"techage:generator", "techage:generator_on"}, {
local nvm = techage.get_nvm(pos)
if topic == "trigger" then
nvm.firebox_trigger = 3
if nvm.running then
return math.max((nvm.provided or PWR_CAPA) / PWR_CAPA, 0.02)
if techage.is_running(nvm) then
return math.max((nvm.provided or PWR_PERF) / PWR_PERF, 0.02)
else
return 0
end
@ -230,6 +233,28 @@ techage.register_node({"techage:generator", "techage:generator_on"}, {
end,
})
-- used by power terminal
control.register_nodes({"techage:generator", "techage:generator_on"}, {
on_receive = function(pos, tlib2, topic, payload)
end,
on_request = function(pos, tlib2, topic)
if topic == "info" then
local nvm = techage.get_nvm(pos)
local meta = M(pos)
return {
type = S("TA3 Generator"),
number = meta:get_string("node_number") or "",
running = techage.is_running(nvm) or false,
available = PWR_PERF,
provided = nvm.provided or 0,
termpoint = meta:get_string("termpoint"),
}
end
return false
end,
}
)
minetest.register_craft({
output = "techage:generator",
recipe = {

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -20,7 +20,7 @@ local S = techage.S
local firebox = techage.firebox
local fuel = techage.fuel
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local liquid = networks.liquid
local CYCLE_TIME = 2
local BURN_CYCLE_FACTOR = 0.5
@ -115,44 +115,10 @@ minetest.register_node("techage:oilfirebox", {
minetest.after(1, start_firebox, pos, nvm)
end
end,
liquid = {
capa = fuel.CAPACITY,
fuel_cat = fuel.BT_BITUMEN,
peek = liquid.srv_peek,
put = function(pos, indir, name, amount)
if fuel.valid_fuel(name, fuel.BT_BITUMEN) then
local leftover = liquid.srv_put(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
nvm.liquid = nvm.liquid or {}
nvm.liquid.amount = nvm.liquid.amount or 0
start_firebox(pos, nvm)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", fuel.formspec(nvm))
end
return leftover
end
return amount
end,
take = function(pos, indir, name, amount)
amount, name = liquid.srv_take(pos, indir, name, amount)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", fuel.formspec(nvm))
end
return amount, name
end
},
networks = {
pipe2 = {
sides = techage.networks.AllSides, -- Pipe connection sides
ntype = "tank",
},
},
})
Pipe:add_secondary_node_names({"techage:oilfirebox"})
liquid.register_nodes({"techage:oilfirebox"},
Pipe, "tank", nil, fuel.get_liquid_table(fuel.BT_OIL, fuel.CAPACITY, start_firebox))
techage.register_node({"techage:oilfirebox"}, {
@ -161,7 +127,7 @@ techage.register_node({"techage:oilfirebox"}, {
if topic == "state" then
return nvm.running and "running" or "stopped"
elseif topic == "fuel" then
return techage.fuel.get_fuel_amount(nvm)
return fuel.get_fuel_amount(nvm)
else
return "unsupported"
end

View File

@ -19,7 +19,6 @@ local S = techage.S
-- Consumer Related Data
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
local power = techage.power
local STANDBY_TICKS = 3
local COUNTDOWN_TICKS = 4
@ -49,7 +48,7 @@ local function formspec(self, pos, nvm)
default.gui_slots..
"box[0,-0.1;4.8,0.5;#c6e8ff]"..
"label[1,-0.1;"..minetest.colorize("#000000", S("Digtron Battery")).."]"..
power.formspec_label_bar(pos, 0, 0.8, S("Load"), TOTAL_MAX, total, S("Coal Equivalents"))..
techage.formspec_label_bar(pos, 0, 0.8, S("Load"), TOTAL_MAX, total, S("Coal Equivalents"))..
"image_button[2.6,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
"tooltip[2.6,2;1,1;"..self:get_state_tooltip(nvm).."]"..
"image[3.75,2;1,1;"..techage.get_power_image(pos, nvm).."]"
@ -163,7 +162,7 @@ techage.register_consumer("digtron_battery", S("Digtron Battery"), { act = tiles
groups = {choppy=2, cracky=2, crumbly=2, digtron=5},
sounds = default.node_sound_wood_defaults(),
power_consumption = {0,25,25,25},
power_sides = techage.networks.AllSides,
power_sides = {L=1, R=1, U=1, D=1, F=1, B=1},
}, {false, false, true, false})
minetest.register_craft({

View File

@ -50,6 +50,8 @@ techage.Items = {
ta2_forceload = "techage:forceload",
ta2_driveaxle = "techage:axle",
ta2_generator = "techage:ta2_generator_off",
ta2_winch = "techage:ta2_winch",
ta2_weight_chest = "techage:ta2_weight_chest",
---------------------
techage_ta3 = "techage_ta3.png",
techage_ta31 = "techage_ta3b.png",
@ -182,6 +184,9 @@ techage.Items = {
ta4_waterinlet = "techage:ta4_waterinlet",
ta4_laser = "techage:ta4_laser_emitter",
ta4_concentrator = "techage:ta4_concentrator27",
ta4_electricmeter = "techage:ta4_electricmeter",
ta4_transformer = "techage:ta4_transformer",
power_reduction = "techage_power_reduction.png",
--ta4_ "",
}

View File

@ -3,6 +3,8 @@ techage.manual_DE = {}
techage.manual_DE.aTitel = {
"1,Tech Age Mod",
"2,Hinweise",
"2,Änderungen ab Version 1.0",
"3,Tipps zur Umstellung",
"2,Erze und Mineralien",
"3,Meridium",
"3,Usmium",
@ -10,7 +12,6 @@ techage.manual_DE.aTitel = {
"3,Erdöl",
"3,Bauxit",
"3,Basalt",
"2,History",
"1,TA1: Eisenzeitalter",
"2,Köhler / Coal Pile",
"2,Kohlebrenner / Coal Burner",
@ -29,6 +30,9 @@ techage.manual_DE.aTitel = {
"3,TA2 Dampfleitungen / Steam Pipe",
"3,TA2 Antriebsachsen / TA2 Drive Axle",
"3,TA2 Stromgenerator / TA2 Power Generator",
"2,TA2 Energiespeicher",
"3,TA2 Seilwinde / TA2 Winch",
"3,TA2 Gewichtekiste / TA2 Weight Chest",
"2,Items schieben und sortieren",
"3,Röhren / TechAge Tube",
"3,Röhren Konzentrator / Tube Concentrator",
@ -56,6 +60,7 @@ techage.manual_DE.aTitel = {
"3,TA3 Generator",
"3,TA3 Kühler / Cooler",
"2,Elektrischer Strom",
"3,Bedeutung von Speichersystemen",
"3,TA Stromkabel / Electric Cable",
"3,TA Verteilerdose / Electric Junction Box",
"3,TA Stromleitung / Power Line",
@ -69,7 +74,6 @@ techage.manual_DE.aTitel = {
"3,TA3 Akku Block / Akku Box",
"3,TA3 Strom Terminal / Power Terminal",
"3,TA3 Elektromotor / TA3 Electric Motor",
"3,TA3 Strom Terminal / Power Terminal",
"2,TA3 Industrieofen",
"3,TA3 Ofen-Ölbrenner / Furnace Oil Burner",
"3,TA3 Ofenoberteil / Furnace Top",
@ -146,6 +150,10 @@ techage.manual_DE.aTitel = {
"3,TA4 Generator",
"3,TA4 Rohrzulauf / TA4 Pipe Inlet",
"3,TA4 Röhre / Pipe",
"2,Stromverteilung",
"3,TA4 Trenntransformator / TA4 Isolation Transformer",
"3,TA4 Stromzähler / TA4 Electric Meter",
"3,TA4 Laser",
"2,Wasserstoff",
"3,Elektrolyseur",
"3,Brennstoffzelle",
@ -197,7 +205,6 @@ techage.manual_DE.aTitel = {
"3,TA4 Elektronikfabrik / Electronic Fab",
"3,TA4 Injektor / Injector",
"3,TA4 Recycler",
"3,TA4 Laser",
}
techage.manual_DE.aText = {
@ -233,6 +240,22 @@ techage.manual_DE.aText = {
"\n"..
"Mit TA4 kommen weitere Stromquellen dazu\\, aber auch höhere logistische Herausforderungen (Stromtrassen\\, Item Transport).\n"..
"\n",
"Ab V1.0 (17.07.2021) hat sich folgendes geändert:\n"..
"\n"..
" - Der Algorithmus zur Berechnung der Stromverteilung hat sich geändert. Energiespeichersystem werden dadurch wichtiger. Diese gleichen Schankungen aus\\, was bei größeren Netzen mit mehreren Generatoren wichtig wird.\n"..
" - Aus diesem Grund hat TA2 seinen eigenen Energiespeicher erhalten.\n"..
" - Die Akkublöcke aus TA3 dienen auch als Energiespeicher. Ihre Funktionsweise wurde entsprechend angepasst.\n"..
" - Das TA4 Speichersystem wurde überarbeitet. Die Wärmetauscher (heatexchanger) haben eine neue Nummer bekommen\\, da die Funktionalität vom unteren in den mittleren Block verschoben wurde. Sofern diese ferngesteuert wurden\\, muss die Knotennummer angepasst werden. Die Generatoren haben kein eigenes Menü mehr\\, sondern werden nur noch über den Wärmetauscher ein-/ausgeschaltet. Wärmetauscher und Generator müssen jetzt am gleichen Netz hängen!\n"..
" - Mehrere Stromnetze können jetzt über einen TA4 Transformator Blöcke gekoppelt werden.\n"..
" - Neu ist auch ein TA4 Stromzähler Block für Unternetze.\n"..
"\n",
"Viele weitere Blöcke haben kleinere Änderungen bekommen. Daher kann es sein\\, dass Maschinen oder Anlagen nach der Umstellung nicht gleich wieder anlaufen. Sollte es zu Störungen kommen\\, helfen folgende Tipps:\n"..
"\n"..
" - Maschinen aus- und wieder eingeschalten\n"..
" - ein Stromkabel-Block entfernen und wieder setzen\n"..
" - den Block ganz entfernen und wieder setzen\n"..
" - mindestens ein Akkublock oder Speichersystem in jedes Netzwerk\n"..
"\n",
"Techage fügt dem Spiel einige neue Items hinzu:\n"..
"\n"..
" - Meridium - eine Legierung zur Herstellung von leuchtenden Werkzeugen in TA1\n"..
@ -264,21 +287,13 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
"Basalt entsteht nur\\, wenn Lava und Wasser zusammenkommen.\n"..
"Basalt entsteht nur\\, wenn Lava und Wasser zusammen kommen.\n"..
"Dazu sollte man am besten eine Anlage aufbauen\\, bei der eine Lava- und eine Wasserquelle zusammenfließen.\n"..
"Dort wo sich beide Flüssigkeiten treffen\\, entsteht Basalt.\n"..
"Einen automatisierten Basalt Generator kann man mit dem Sign Bot aufbauen.\n"..
"\n"..
"\n"..
"\n",
" - 28.09.2019: Um Solaranlage erweitert\n"..
" - 05.10.2019: Daten zur Solaranlage und Beschreibung zum Wechselrichter und zum Power-Terminal geändert\n"..
" - 18.11.2019: Kapitel für Erze\\, Reaktor\\, Aluminium\\, Silo\\, Bauxit\\, Ofenheizung\\, Kieswaschanlage hinzugefügt\n"..
" - 22.02.2020: Korrekturen und Kapitel zum Update\n"..
" - 29.02.2020: ICTA Controller hinzugefügt und weitere Korrekturen\n"..
" - 14.03.2020 Lua Controller hinzugefügt und weitere Korrekturen\n"..
" - 22.03.2020 Weitere TA4 Blöcke hinzugefügt\n"..
"\n",
"In TA1 geht es darum\\, mit einfachen Werkzeugen und Gerätschaften ausreichend Erze zu schürfen und Holzkohle herzustellen\\, so dass damit TA2 Maschinen hergestellt und betrieben werden können.\n"..
"\n"..
"Natürlich muss es für ein Eisenzeitalter auch Eisen geben und nicht nur Stahl (steel)\\, wie in \"Minetest Game\". Daher wurden einige Rezepte geändert\\, so dass zuerst Eisen hergestellt werden muss und erst später dann Stahl.\n"..
@ -377,7 +392,7 @@ techage.manual_DE.aText = {
"Die Feuerbox muss mit Kohle oder Holzkohle gefüllt werden.\n"..
"Wenn das Wasser heiß ist (Temperaturanzeige ganz oben)\\, kann die Dampfmaschine am Schwungrad gestartet werden.\n"..
"\n"..
"Die Dampfmaschine leistet 25 ku\\, kann damit mehrere Maschinen gleichzeitig antreiben.\n"..
"Die Dampfmaschine leistet 25 ku und kann damit mehrere Maschinen gleichzeitig antreiben.\n"..
"\n"..
"\n"..
"\n",
@ -403,7 +418,7 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
"Die Antriebsachsen dienen zur Kraftübertragung von der Dampfmaschine zu anderen Maschinen. Die maximale Länge einer Antriebsachse beträgt 8 Blöcke. Über Getriebeboxen können auch größere Strecken überbrückt\\, sowie Abzweigungen und Richtungswechsel realisiert werden.\n"..
"Die Antriebsachsen dienen zur Kraftübertragung von der Dampfmaschine zu anderen Maschinen. Die maximale Länge einer Antriebsachse beträgt 10 Blöcke. Über Getriebeboxen können auch größere Strecken überbrückt\\, sowie Abzweigungen und Richtungswechsel realisiert werden.\n"..
"\n"..
"\n"..
"\n",
@ -415,6 +430,22 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
"Bei größeren Anlagen mit mehreren Dampfmaschinen oder vielen angetriebenen Maschinen empfiehlt sich ein Energiespeicher. Der Energiespeicher bei TA2 arbeitet mit Lageenergie. Dazu wird Balast (Steine\\, Kies) in einer Kiste mit Hilfe einer Seilwinde in die Höhe gezogen. Ist überschüssige Energie im Achsen-Netzwerk vorhanden\\, so wird die Kiste nach oben gezogen. Wird kurzfristig mehr Energie benötigt\\, als die Dampfmaschine liefern kann\\, so gibt der Energiespeicher die gespeicherte Energie wieder ab\\, und die Balast-Kiste bewegt sich wieder nach unten.\n"..
"\n"..
"Der Energiespeicher besteht aus mehreren Blöcken und muss wie im Plan rechts abgebildet\\, zusammen gebaut werden.\n"..
"\n"..
"Um die maximale Speicherkapazität zu erreichen\\, muss die Kiste mit Gewichten komplett gefüllt\\, und der Mast inklusive der zwei Getriebeboxen 12 Blöcke hoch sein. Kleinere Aufbauten sind aber auch möglich.\n"..
"\n"..
"\n"..
"\n",
"Die Seilwinde muss mit einer Getriebebox verbunden werden und kann so überschüssige Energie aufnehmen und damit eine Gewichtekiste nach oben ziehen. Die maximale Seillänge beträgt 10 Blöcke.\n"..
"\n"..
"\n"..
"\n",
"Diese Kiste muss mit bis zu 10 Blöcken Abstand unter die Seilwinde gesetzt und mit Pflastersteinen Kies oder Sand gefüllt werden. Ist das Mindestgewicht von einem Stack (99+ Items) erreicht und überschüssige Energie vorhanden\\, wird die Kiste automatisch über eine Seil mit der Seilwinde verbunden und in die Höhe gezogen.\n"..
"\n"..
"\n"..
"\n",
"Um Gegenstände (Items) von einer Verarbeitungsstation zur nächsten weiter zu transportieren\\, werden Schieber und Röhren verwendet. Siehe Plan.\n"..
"\n"..
"\n"..
@ -553,7 +584,7 @@ techage.manual_DE.aText = {
"\n"..
"Der Boiler muss mit Wasser gefüllt werden. Dazu bis zu 10 Eimer Wasser in den Boiler füllen.\n"..
"Die Feuerbox muss mit Kohle oder Holzkohle gefüllt werden.\n"..
"Wenn das Wasser heiß ist\\, kann das Ventil am Boiler geöffnet und anschließend die Generator gestartet werden.\n"..
"Wenn das Wasser heiß ist\\, kann der Generator gestartet werden.\n"..
"\n"..
"Das Kraftwerk kann alternativ auch mit einem Ölbrenner ausgestattet und dann mit Öl betrieben werden.\n"..
"Das Öl kann über eine Pumpe und Ölleitung nachgefüllt werden.\n"..
@ -593,13 +624,13 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
"In TA3 (und TA4) werden die Maschinen mit Strom angetrieben. Dazu müssen die Maschinen und Generatoren mit Stromkabel verbunden werden.\n"..
"In TA3 (und TA4) werden die Maschinen mit Strom angetrieben. Dazu müssen die Maschinen\\, Speichersysteme und Generatoren mit Stromkabel verbunden werden.\n"..
"TA3 besitzt 2 Arten von Stromkabel:\n"..
"\n"..
" - Isolierte Kabel (TA Stromkabel) für die lokale Verkabelung im Boden oder in Gebäuden. Diese Kabel lassen sich in der Wand oder im Boden verstecken (können mit der Kelle \"verputzt\" werden).\n"..
" - Überlandleitungen (TA Stromleitung) für Freiluftverkabelung über große Strecken. Diese Kabel sind geschützt\\, können also von anderen Spielern nicht entfernt werden.\n"..
"\n"..
"Mehrere Verbraucher und Generatoren können in einem Stromnetzwerk zusammen betrieben werden. Mit Hilfe der Verteilerdosen können so große Netzwerke aufgebaut werden.\n"..
"Mehrere Verbraucher\\, Speichersysteme und Generatoren können in einem Stromnetzwerk zusammen betrieben werden. Mit Hilfe der Verteilerdosen können so Netzwerke aufgebaut werden.\n"..
"Wird zu wenig Strom bereitgestellt\\, gehen die Verbraucher aus.\n"..
"In diesem Zusammenhang ist auch wichtig\\, dass die Funktionsweise von Forceload Blöcken verstanden wurde\\, denn bspw. Generatoren liefern nur Strom\\, wenn der entsprechende Map-Block geladen ist. Dies kann mit einen Forceload Block erzwungen werden.\n"..
"\n"..
@ -607,8 +638,25 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
"Speichersysteme im Stromnetz erfüllen zwei Aufgaben:\n"..
"\n"..
" - Um Bedarfsspitzen abzufangen: Alle Generatoren liefern immer gerade soviel Leistung\\, wie benötigt wird. Werden aber Verbraucher ein/ausgeschaltet oder kommt es aus anderen Gründen zu Bedarfsschwankungen\\, so können Verbraucher kurzzeitig ausfallen. Um dies zu verhindern\\, sollte immer mindestens ein Akkublock in jedem Netzwerk vorhanden sein. Dieser dient aus Puffer und gleicht diese Schwankungen im Sekundenbereich aus.\n"..
" - Um regenerative Energie zu speichern: Solar und Wind stehen nicht 24 Stunden am Tag zur Verfügung. Damit die Stromversorgung nicht ausfällt\\, wenn kein Strom produziert wird\\, müssen ein oder mehrere Speichersysteme im Netzwerk verbaut werden. Alternativ können die Lücken auch mit Öl/Kohle-Strom überbrückt werden.\n"..
"\n"..
"Ein Speichersystem gibt seine Kapazität in kud an\\, also ku pro day (Tag). Bspw. ein Speichersystem mit 100 kud liefert 100 ku einen Spieltag lang\\, oder auch 10 ku für 10 Spieltage.\n"..
"\n"..
"Alle TA3/TA4 Energiequellen besitzen eine einstellbare Ladecharakteristik. Standardmäßig ist diese auf \"80% - 100%\" eingestellt. Dies bedeutet\\, dass die Leistung ab 80% Füllung des Speichersystems immer weiter reduziert wird\\, bis sie bei 100 % komplett abschaltet. Sofern Strom im Netzwerk benötigt wird\\, werden die 100 % nie erreicht\\, da die Leistung des Generators irgendwann auf den Strombedarf im Netzwerk abgesunken ist und damit das Speichersystem nicht mehr geladen\\, sondern nur noch die Verbraucher bedient werden.\n"..
"\n"..
"Dies hat mehrere Vorteile:\n"..
"\n"..
" - Die Ladecharakteristik ist einstellbar. Damit kann man bspw. Öl/Kohle Energiequellen bei 60% und die regenerativen Energiequellen erst bei 80% zurückfahren. Damit wird nur Öl/Kohle verbrannt\\, wenn nicht ausreichend regenerativen Energiequellen zur Verfügung stehen.\n"..
" - Mehrere Energiequellen können parallel betrieben werden und werden dabei nahezu gleichmäßig belastet\\, denn alle Energiequellen arbeiten bspw. bis 80% Ladekapazität des Speichersystems mit ihrer vollen Leistung und fahren dann gleichzeitig ihre Leistung zurück.\n"..
" - Alle Speichersysteme in einem Netzwerk bilden einen großen Puffer. An jedem Speichersystem aber auch am Strom Terminal kann immer die Ladekapazität und der Füllungsgrad des gesamten Speichersystems in Prozent abgelesen werden.\n"..
"\n"..
"\n"..
"\n",
"Für die lokale Verkabelung im Boden oder in Gebäuden.\n"..
"Abzweigungen können mit Hilfe von Verteilerdosen realisiert werden. Die maximale Kabellänge zwischen Maschinen oder Verteilerdosen beträgt 1000 m. Es können maximale 1000 Knoten in einem Strom-Netzwerk verbunden werden. Als Knoten zählen alle Generatoren\\, Akkus\\, Verteilerdosen und Maschinen.\n"..
"Abzweigungen können mit Hilfe von Verteilerdosen realisiert werden. Die maximale Kabellänge zwischen Maschinen oder Verteilerdosen beträgt 1000 m. Es können maximale 1000 Knoten in einem Strom-Netzwerk verbunden werden. Als Knoten zählen alle Blöcke mit Stromanschluss\\, also auch Verteilerdosen.\n"..
"\n"..
"Da die Stromkabel nicht automatisch geschützt sind\\, wird für längere Strecken die Überlandleitungen (TA Stromleitung) empfohlen.\n"..
"\n"..
@ -622,7 +670,6 @@ techage.manual_DE.aText = {
"\n"..
"\n",
"Mit der Verteilerdose kann Strom in bis zu 6 Richtungen verteilt werden. Verteilerdosen können auch mit der Kelle verputzt (versteckt) und wieder sichtbar gemacht werden.\n"..
"Wird mit dem TechAge Info Werkzeug (Schraubenschlüssel) auf die Verteilerdose geklickt\\, wird angezeigt\\, wie viel Leistung die Generatoren liefern bzw. die Verbraucher im Netzwerk beziehen.\n"..
"\n"..
"\n"..
"\n",
@ -663,17 +710,24 @@ techage.manual_DE.aText = {
"\n"..
"\n",
"Der Akku Block dient zur Speicherung von überschüssiger Energie und gibt bei Stromausfall automatisch Strom ab (soweit vorhanden).\n"..
"Der Akku Block ist eine sekundäre Stromquelle. Das bedeutet\\, bei Strombedarf werden zuerst die Generatoren genutzt. Nur wenn der Strom im Netz nicht ausreicht\\, springt der Akku Block ein. Das Gleiche gilt auch für die Stromaufnahme. Daher kann auch kein Akku mit einem anderen Akku geladen werden.\n"..
"Der Akku liefert 10 ku bzw. nimmt 10 ku auf.\n"..
"Bei Volllast kann ein Akku 400 s lang Strom aufnehmen und wenn er voll ist\\, auch wieder abgeben. Dies entspricht 8 h Spielzeit bei einem normalen Spieltag von 20 min.\n"..
"Mehrere Akku Blocks zusammen bilden ein TA3 Energiespeichersystem. Jeder Akku Block hat eine Anzeige für den Ladezustand und für die gespeicherte Ladung\\, wobei hier immer die Werte für das gesamte Netzwerk angezeigt werden. Die gespeicherte Ladung wird in \"kud\" also \"ku-days\" angezeigt (analog zu kWh) 5 kud entspricht damit bspw. 5 ku für einen Spieltag (20 min) oder 1 ku für 5 Spieltage.\n"..
"\n"..
"Ein Akku Block hat 3.33 kud.\n"..
"\n"..
"\n"..
"\n",
"Das Strom-Terminal muss mit dem Stromnetz verbunden werden. Es zeigt Daten aus dem Stromnetz an.\n"..
"\n"..
"In der oberen Hälfte werden nur die Daten eines ausgewählten Typs ausgegeben. Wird als Typ bspw. \"Kraftwerk\" gewählt\\, so werden nur die Daten von Öl- und Kohlekraftwerken gesammelt und ausgegeben. Links werden die Daten von Generatoren (Stromabgabe) und rechts die Daten von Energiespeichern (Stromaufnahme) ausgegeben. Beim Akkublocks bspw. wird beides ausgegeben\\, da der Akku Strom aufnehmen und abgeben kann.\n"..
"In der oberen Hälfte werden die wichtigsten Größen ausgegeben:\n"..
"\n"..
"In der unteren Hälfte werden die Daten aller Generatoren und Speichersystemen des ganzen Stromnetzen zusammengefasst ausgegeben.\n"..
" - aktuelle/maximale Generatorleistung\n"..
" - aktueller Stromaufnahme aller Verbraucher\n"..
" - aktueller Ladestrom in/aus dem Speichersystems\n"..
" - aktuellen Ladezustand des Speichersystems in Prozent\n"..
"\n"..
"In der unteren Hälfte wird die Anzahl der Netzwerkblöcke ausgegeben.\n"..
"\n"..
"Über den Reiter \"console\" können weitere Daten zu den Generatoren und Speichersystemen abgefragt werden.\n"..
"\n"..
"\n"..
"\n",
@ -684,14 +738,6 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
"Das Strom-Terminal muss mit dem Stromnetz verbunden werden. Es zeigt Daten aus dem Stromnetz an.\n"..
"\n"..
"In der oberen Hälfte werden nur die Daten eines ausgewählten Typs ausgegeben. Wird als Typ bspw. \"Kraftwerk\" gewählt\\, so werden nur die Daten von Öl- und Kohlekraftwerken gesammelt und ausgegeben. Links werden die Daten von Generatoren (Stromabgabe) und rechts die Daten von Energiespeichern (Stromaufnahme) ausgegeben. Beim Akkublocks bspw. wird beides ausgegeben\\, da der Akku Strom aufnehmen und abgeben kann.\n"..
"\n"..
"In der unteren Hälfte werden die Daten aller Generatoren und Speichersystemen des ganzen Stromnetzen zusammengefasst ausgegeben.\n"..
"\n"..
"\n"..
"\n",
"Der TA3 Industrieofen dient als Ergänzung zu normalen Ofen (furnace). Damit können alle Waren mit \"Koch\" Rezepten\\, auch im Industrieofen hergestellt werden. Es gibt aber auch spezielle Rezepte\\, die nur im Industrieofen hergestellt werden können.\n"..
"Der Industrieofen hat sein eigenes Menü zur Rezeptauswahl. Abhängig von den Waren im Industrieofen Inventar links kann rechts das Ausgangsprodukt gewählt werden.\n"..
"\n"..
@ -1116,7 +1162,8 @@ techage.manual_DE.aText = {
"",
"Das Techage Info Tool (Schraubenschlüssel) hat verschiedene Funktionen. Er zeigt die Uhrzeit\\, die Position\\, die Temperatur und das Biome an\\, wenn auf einen unbekannten Block geklickt wird.\n"..
"Wird auf einen TechAge Block mit Kommandoschnittstelle geklickt\\, werden alle verfügbaren Daten abgerufen (siehe auch \"Logik-/Schalt-Blöcke\").\n"..
"Bei Strom-Verteilerdosen werden die benachbarten Netzwerkteilnehmer (bis zu 50 Meter weit) mit einem blauen Käfig angezeigt.\n"..
"\n"..
"Mit Shift+Rechtsklick kann bei einigen Blöcken ein erweitertes Menü geöffnet werden. Hier lassen sich je nach Block weitere Daten abrufen oder spezielle Einstellungen vornehmen. Bei einem Generator kann bspw. die Ladekurve/abschaltung programmiert werden. \n"..
"\n"..
"\n"..
"\n",
@ -1150,9 +1197,7 @@ techage.manual_DE.aText = {
"\n"..
"\n",
"Der Windkraftanlagenblock (Rotor) ist das Herzstück der Windkraftanlage. Dieser Block muss oben auf den Mast gesetzt werden. Idealerweise auf Y = 15\\, dann bleibst du noch gerade innerhalb eines Map-/Forceload-Blocks.\n"..
"Nach dem Setzen des Blocks wird ein Check durchgeführt\\, ob alle Bedingungen für den Betrieb der Windkraftanlage erfüllt sind. Sofern alle Bedingungen erfüllt sind\\, erscheinen beim Setzen dieses Blocks auch automatisch die Rotorblätter (Flügel). Anderenfalls wird dir eine Fehlermeldung angezeigt. \n"..
"\n"..
"Durch Schlagen auf den Block kann der Check wiederholt werden.\n"..
"Beim Starten der Windkraftanlage werden alle Bedingungen für den Betrieb der Windkraftanlage überprüft. Sofern alle Bedingungen erfüllt sind\\, erscheinen auch automatisch die Rotorblätter (Flügel). Anderenfalls wird eine Fehlermeldung angezeigt. \n"..
"\n"..
"\n"..
"\n",
@ -1224,11 +1269,13 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
"Der TA4 Energiespeicher ersetzt den Batterie Block aus TA3.\n"..
"\n"..
"Der Energiespeicher besteht aus einer Betonhülle (Concrete Block) gefüllt mit Gravel. Es gibt 3 Größen vom Speicher:\n"..
"\n"..
" - Hülle mit 5x5x5 Concrete Blocks\\, gefüllt mit 27 Gravel\\, Speicherkapazität: 1/2 Tag bei 60 ku\n"..
" - Hülle mit 7x7x7 Concrete Blocks\\, gefüllt mit 125 Gravel\\, Speicherkapazität: 2\\,5 Tage bei 60 ku\n"..
" - Hülle mit 9x9x9 Concrete Blocks\\, gefüllt mit 343 Gravel\\, Speicherkapazität: 6\\,5 Tage bei 60 ku\n"..
" - Hülle mit 5x5x5 Concrete Blocks\\, gefüllt mit 27 Gravel\\, Speicherkapazität: 22.5 kud\n"..
" - dHülle mit 7x7x7 Concrete Blocks\\, gefüllt mit 125 Gravel\\, Speicherkapazität: 104 kud\n"..
" - Hülle mit 9x9x9 Concrete Blocks\\, gefüllt mit 343 Gravel\\, Speicherkapazität: 286 kud\n"..
"\n"..
"In der Betonhülle darf ein Fenster aus einem Obsidian Glas Block sein. Dieses muss ziemlich in der Mitte der Wand platziert werden. Durch dieses Fenster sieht man\\, ob der Speicher mehr als 80 % geladen ist. Im Plan rechts sieht man den Aufbau aus TA4 Wärmetauscher bestehend aus 3 Blöcken\\, der TA4 Turbine und dem TA4 Generator. Beim Wärmetauscher ist auf die Ausrichtung zu achten (der Pfeil bei Block 1 muss zur Turbine zeigen).\n"..
"\n"..
@ -1236,14 +1283,13 @@ techage.manual_DE.aText = {
"Sowohl der Generator als auch der Wärmetauscher haben einen Stromanschluss und müssen mit dem Stromnetz verbunden werden.\n"..
"\n"..
"Im Prinzip arbeitet das das Wärmespeichersystem genau gleich wie die Akkus\\, nur mit viel mehr Speicherkapazität. \n"..
"Der Wärmespeicher kann 60 ku aufnehmen und abgeben.\n"..
"\n"..
"Damit das Wärmespeichersystem funktioniert\\, müssen alle Blöcke (auch Betonhülle und Gravel) mit Hilfe eines Forceloadblockes geladen sein.\n"..
"\n"..
"\n"..
"\n",
"Der Wärmetauscher besteht aus 3 Teilen\\, die aufeinander gesetzt werden müssen\\, wobei der Pfeil des ersten Blockes Richtung Turbine zeigen muss. Die Rohrleitungen müssen mit den gelben TA4 Röhren aufgebaut werden.\n"..
"Der Wärmetauscher muss am Stromnetz angeschlossen werden. Der Wärmetauscher lädt den Energiespeicher wieder auf\\, wenn ausreichend Strom zur Verfügung steht und der Energiespeicher weniger als 95 % geladen ist. Der Wärmetauscher nimmt dabei 60 ku auf.\n"..
"Der Wärmetauscher muss am Stromnetz angeschlossen werden. Über den Wärmetauscher wird der Energiespeicher wieder aufgeladen\\, sofern ausreichend Strom zur Verfügung steht.\n"..
"\n"..
"\n"..
"\n",
@ -1251,9 +1297,9 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
"Der Generator dient zur Stromerzeugung. Daher muss auch der Generator am Stromnetz angeschlossen werden. \n"..
"Der Generator ist Teil des Energiespeichers. Er dient zur Stromerzeugung und gibt damt die Energie des Energiespeichers wieder ab. Daher muss auch der Generator am Stromnetz angeschlossen werden. \n"..
"\n"..
"Der Generator kann 60 ku abgeben.\n"..
"Wichtig: Wärmetauscher und Generator müssen mit ein und demselben Stromnetz verbunden sein!\n"..
"\n"..
"\n"..
"\n",
@ -1268,6 +1314,34 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
"Mit Hilfe von Stromkabeln und Verteilerdosen können Stromnetze von bis zu 1000 Blöcke/Knoten aufgebaut werden. Hierbei ist aber zu beachten\\, dass Verteilerdosen auch mitgezählt werden müssen. Somit können bis zu 500 Generatoren/Speichersysteme/Maschinen/Lampen an einem Stromnetz hängen.\n"..
"\n"..
"Mit Hilfe von Trenntransformator und Stromzähler können Netzwerke zu noch größeren Strukturen verbunden werden.\n"..
"\n"..
"\n"..
"\n",
"Mit Hilfe eines Trenntransformators können zwei Stromnetze zu einem größeren Netzwerk verbunden werden. Der Trenntransformator kann Strom in beide Richtungen übertragen.\n"..
"\n"..
"Der Trenntransformator kann bis zu 100 ku übertragen.\n"..
"\n"..
"\n"..
"\n",
"Mit Hilfe eines Stromzählers können zwei Stromnetze zu einem größeren Netzwerk verbunden werden. Der Stromzähler leitet den Strom nur in eine Richtungen weiter (Pfeil beachten). Die Menge an Strom (in kud) wird gemessen und angezeigt. Die Strommenge kann auch über das Kommando 'consumption' durch einen Lua Controller abgefragt werden.\n"..
"\n"..
"Der Stromzähler kann bis zu 200 ku durchleiten.\n"..
"\n"..
"\n"..
"\n",
"Der TA4 Laser dient zur kabellosen Stromübertagung. Dazu sind zwei Blöcke notwendig: TA4 Laserstrahl Sender und TA4 Laserstrahl Empfänger. Zwischen beiden Blöcken muss sich eine Luftstrecke befinden\\, so dass der Laserstrahl vom Sender bis zum Empfänger aufgebaut werden kann.\n"..
"\n"..
"Zuerst muss der Sender platziert werden. Dieser schaltet sofort den Laserstahls ein und zeigt damit mögliche Positionen des Empfängers an. Mögliche Positionen für den Empfänger werden auch über eine Chat-Nachricht ausgegeben. Mit dem Laser lassen sich Strecken bis 96 Blöcke überbrücken.\n"..
"\n"..
"Ist die Verbindung aufgebaut (es muss dazu noch kein Strom fließen)\\, wird dies über den Info-Text des Senders und auch des Empfängers angezeigt.\n"..
"\n"..
"Die Laserblöcke selbst benötigen keinen Strom.\n"..
"\n"..
"\n"..
"\n",
"Strom kann mittels Elektrolyse in Wasserstoff und Sauerstoff aufgespalten werden. Auf der anderen Seite kann über eine Brennstoffzelle Wasserstoff mit Sauerstoff aus der Luft wieder in Strom umgewandelt werden.\n"..
"Damit können Stromspitzen oder ein Überangebot an Strom in Wasserstoff umgewandelt und so gespeichert werden.\n"..
"\n"..
@ -1284,6 +1358,8 @@ techage.manual_DE.aText = {
"Der Elektrolyseur kann bis zu 35 ku an Strom aufnehmen und generiert dann alle 4 s ein Wasserstoff Item.\n"..
"In den Elektrolyseur passen 200 Einheiten Wasserstoff.\n"..
"\n"..
"Der Elektrolyseur besitzt ein Schraubenschlüssel-Menü zur Einstellung der Stromaufnahme und des Abschaltpunkts.\n"..
"\n"..
"\n"..
"\n",
"Die Brennstoffzelle wandelt Wasserstoff in Strom um.\n"..
@ -1630,29 +1706,20 @@ techage.manual_DE.aText = {
"\n"..
"\n"..
"\n",
"Der TA4 Laser dient zur kabellosen Stromübertagung. Dazu sind zwei Blöcke notwendig: TA4 Laserstrahl Sender und TA4 Laserstrahl Empfänger. Zwischen beiden Blöcken muss sich eine Luftstrecke befinden\\, so dass der Laserstrahl vom Sender bis zum Empfänger aufgebaut werden kann.\n"..
"\n"..
"Zuerst muss der Sender platziert werden. Dieser schaltet sofort den Laserstahls ein und zeigt damit mögliche Positionen des Empfängers an. Mögliche Positionen für den Empfänger werden auch über eine Chat-Nachricht ausgegeben. Mit dem Laser lassen sich Strecken bis 96 Blöcke überbrücken.\n"..
"\n"..
"Ist die Verbindung aufgebaut (es muss dazu noch kein Strom fließen)\\, wird dies über den Info-Text des Senders und auch des Empfängers angezeigt.\n"..
"\n"..
"Die Laserblöcke selbst benötigen keinen Strom.\n"..
"\n"..
"t\n"..
"\n",
}
techage.manual_DE.aItemName = {
"techage_ta4",
"",
"",
"",
"",
"meridium",
"usmium",
"baborium",
"oil",
"bauxite",
"basalt",
"",
"techage_ta1",
"",
"",
@ -1672,6 +1739,9 @@ techage.manual_DE.aItemName = {
"ta2_driveaxle",
"ta2_generator",
"",
"ta2_winch",
"ta2_weight_chest",
"",
"tube",
"concentrator",
"ta2_pusher",
@ -1698,6 +1768,7 @@ techage.manual_DE.aItemName = {
"ta3_generator",
"ta3_cooler",
"ta3_powerswitch",
"power_reduction",
"ta3_powercable",
"ta3_powerjunction",
"ta3_powerline",
@ -1711,7 +1782,6 @@ techage.manual_DE.aItemName = {
"ta3_akkublock",
"ta3_powerterminal",
"ta3_motor",
"ta3_powerterminal",
"",
"ta3_furnacefirebox",
"ta3_furnace",
@ -1788,6 +1858,10 @@ techage.manual_DE.aItemName = {
"ta4_generator",
"ta4_pipeinlet",
"ta4_pipe",
"ta4_transformer",
"ta4_transformer",
"ta4_electricmeter",
"ta4_laser",
"ta4_hydrogen",
"ta4_electrolyzer",
"ta4_fuelcell",
@ -1839,7 +1913,6 @@ techage.manual_DE.aItemName = {
"ta4_electronicfab",
"ta4_injector",
"ta4_recycler",
"ta4_laser",
}
techage.manual_DE.aPlanTable = {
@ -1854,6 +1927,7 @@ techage.manual_DE.aPlanTable = {
"",
"",
"",
"",
"coalpile",
"coalburner",
"",
@ -1871,6 +1945,9 @@ techage.manual_DE.aPlanTable = {
"",
"",
"",
"ta2_storage",
"",
"",
"itemtransport",
"",
"",
@ -1991,6 +2068,10 @@ techage.manual_DE.aPlanTable = {
"",
"",
"",
"",
"",
"",
"",
"ta4_reactor",
"",
"",
@ -2039,6 +2120,5 @@ techage.manual_DE.aPlanTable = {
"",
"",
"",
"",
}

View File

@ -3,6 +3,8 @@ techage.manual_EN = {}
techage.manual_EN.aTitel = {
"1,Tech Age Mod",
"2,Hints",
"2,Changes from version 1.0",
"3,Tips on switching",
"2,Ores and Minerals",
"3,Meridium",
"3,Usmium",
@ -29,6 +31,9 @@ techage.manual_EN.aTitel = {
"3,TA2 Steam Pipes",
"3,TA2 Drive Axle / TA2 Gearbox",
"3,TA2 Power Generator",
"2,TA2 energy storage",
"3,TA2 Winch",
"3,TA2 Weight Chest",
"2,Push and sort items",
"3,TechAge Tube",
"3,Tube Concentrator",
@ -56,6 +61,7 @@ techage.manual_EN.aTitel = {
"3,TA3 generator",
"3,TA3 cooler",
"2,Electrical current",
"3,Importance of storage systems",
"3,TA Electric Cable",
"3,TA Electric Junction Box",
"3,TA Power Line",
@ -145,6 +151,10 @@ techage.manual_EN.aTitel = {
"3,TA4 Generator",
"3,TA4 Pipe Inlet",
"3,TA4 Pipe",
"2,Power Distribution",
"3,TA4 Isolation Transformer",
"3,TA4 Electric Meter",
"3,TA4 Laser",
"2,Hydrogen",
"3,Electrolyzer",
"3,Fuel Cell",
@ -196,7 +206,6 @@ techage.manual_EN.aTitel = {
"3,TA4 Electronic Fab",
"3,TA4 Injector",
"3,TA4 Recycler",
"3,TA4 Laser",
}
techage.manual_EN.aText = {
@ -232,6 +241,22 @@ techage.manual_EN.aText = {
"\n"..
"TA4 adds more power sources\\, but also higher logistical challenges (power lines\\, item transport).\n"..
"\n",
"From V1.0 (07/17/2021) the following has changed:\n"..
"\n"..
" - The algorithm for calculating the power distribution has changed. This makes energy storage systems more important. These compensate for fluctuations\\, which is important in larger networks with several generators.\n"..
" - For this reason TA2 got its own energy storage.\n"..
" - The battery blocks from TA3 also serve as energy storage. Their functionality has been adapted accordingly.\n"..
" - The TA4 storage system has been revised. The heat heat exchanger have been given a new number because the functionality has been moved from the lower to the middle block. If these were remotely controlled\\, the node number must be adapted. The generators no longer have their own menu\\, but are only switched on / off via the heat exchanger. The heat exchanger and generator must now be connected to the same network!\n"..
" - Several power grids can now be coupled via a TA4 transformer blocks.\n"..
" - A TA4 electricity meter block for sub-networks is also new.\n"..
" - At least one battery block or a storage system in each network\n"..
"\n",
"Many more blocks have received minor changes. It is therefore possible that machines or systems do not start up again immediately after the changeover. In the event of malfunctions\\, the following tips will help:\n"..
"\n"..
" - Switch machines off and on again\n"..
" - remove a power cable block and put it back in place\n"..
" - remove the block completely and put it back in place\n"..
"\n",
"Techage adds some new items to the game:\n"..
"\n"..
" - Meridium - an alloy for the production of luminous tools in TA1\n"..
@ -402,7 +427,7 @@ techage.manual_EN.aText = {
"\n"..
"\n"..
"\n",
"The drive axles are used to transmit power from the steam engine to other machines. The maximum length of a drive axis is 8 blocks. With TA2 Gearboxes\\, larger distances can be bridged\\, and branches and changes of direction can be realized.\n"..
"The drive axles are used to transmit power from the steam engine to other machines. The maximum length of a drive axis is 10 blocks. With TA2 Gearboxes\\, larger distances can be bridged\\, and branches and changes of direction can be realized.\n"..
"\n"..
"\n"..
"\n",
@ -414,6 +439,20 @@ techage.manual_EN.aText = {
"\n"..
"\n"..
"\n",
"For larger systems with several steam engines or many driven machines\\, an energy storage system is recommended. The energy storage at TA2 works with position energy. For this purpose\\, ballast (stones\\, gravel\\, sand) is pulled up in a chest with the help of a cable winch. If there is excess energy in the axis network\\, the chest is pulled upwards. If more energy is required in the short term than the steam engine can supply\\, the energy store releases the stored energy again and the weight chest moves down again. \n"..
"The energy storage consists of several blocks and must be assembled as shown in the plan on the right. \n"..
"In order to achieve the maximum storage capacity\\, the chest must be completely filled with weights and the mast including the two gear boxes must be 12 blocks high. Smaller structures are also possible.\n"..
"\n"..
"\n"..
"\n",
"The cable winch must be connected to a gear box and can absorb excess energy and thus pull a weight chest upwards. The maximum rope length is 10 blocks. \n"..
"\n"..
"\n"..
"\n",
"This chest must be placed under the winch with a distance of up to 10 blocks and filled with cobblestone\\, gravel or sand. If the minimum weight of a stack (99+ items) is reached and there is excess energy\\, the box is automatically connected to the winch via a rope and pulled up. \n"..
"\n"..
"\n"..
"\n",
"In order to transport objects from one processing station to the next\\, pushers and tubes are used. See plan.\n"..
"\n"..
"\n"..
@ -592,13 +631,13 @@ techage.manual_EN.aText = {
"\n"..
"\n"..
"\n",
"In TA3 (and TA4) the machines are powered by electricity. To do this\\, the machines and generators must be connected with power cables.\n"..
"In TA3 (and TA4) the machines are powered by electricity. To do this\\, machines\\, storage systems\\, and generators must be connected with power cables.\n"..
"TA3 has 2 types of power cables:\n"..
"\n"..
" - Insulated cables (TA power cables) for local wiring in the floor or in buildings. These cables can be hidden in the wall or in the floor (can be \"plastered\" with the trowel).\n"..
" - Overland lines (TA power line) for outdoor cabling over long distances. These cables are protected and cannot be removed by other players.\n"..
"\n"..
"Several consumers and generators can be operated together in a power network. Large networks can be set up with the help of the junction boxes.\n"..
"Several consumers\\, storage systems\\, and generators can be operated together in a power network. Networks can be set up with the help of the junction boxes.\n"..
"If too little electricity is provided\\, consumers run out.\n"..
"In this context\\, it is also important that the functionality of Forceload blocks is understood\\, because generators\\, for example\\, only supply electricity when the corresponding map block is loaded. This can be enforced with a forceload block.\n"..
"\n"..
@ -606,8 +645,25 @@ techage.manual_EN.aText = {
"\n"..
"\n"..
"\n",
"Storage systems in the power grid fulfill two tasks:\n"..
"\n"..
" - To cope with peaks in demand: All generators always deliver just as much power as is needed. However\\, if consumers are switched on/off or there are fluctuations in demand for other reasons\\, consumers can fail for a short time. To prevent this\\, there should always be at least one battery block in every network. This serves as a buffer and compensates for these fluctuations in the seconds range.\n"..
" - To store regenerative energy: Solar and wind are not available 24 hours a day. So that the power supply does not fail when no electricity is produced\\, one or more storage systems must be installed in the network. Alternatively\\, the gaps can also be bridged with oil/coal electricity.\n"..
"\n"..
"A storage system indicates its capacity in kud\\, i.e. ku per day. For example\\, a storage system with 100 kud delivers 100 ku for one game day\\, or 10 ku for 10 game days.\n"..
"\n"..
"All TA3/TA4 energy sources have adjustable charging characteristics. By default this is set to \"80% - 100%\". This means that when the storage system is 80% full\\, the output is reduced further and further until it switches off completely at 100%. If electricity is required in the network\\, 100% will never be reached\\, since the power of the generator has at some point dropped to the electricity demand in the network and the storage system is no longer charged\\, but only the consumers are served.\n"..
"\n"..
"This has several advantages:\n"..
"\n"..
" - The charging characteristics are adjustable. This means\\, for example\\, that oil/coal energy sources can be reduced at 60% and regenerative energy sources only at 80%. This means that oil/coal is only burned if there are not enough renewable energy sources available.\n"..
" - Several energy sources can be operated in parallel and are loaded almost evenly\\, because all energy sources work\\, for example\\, up to 80% of the storage system's charging capacity at their full capacity and then reduce their capacity at the same time.\n"..
" - All storage systems in a network form a large buffer. The charging capacity and the filling level of the entire storage system can always be read in percent on every storage system\\, but also on the electricity terminal.\n"..
"\n"..
" \n"..
"\n",
"For local wiring in the floor or in buildings.\n"..
"Branches can be realized using junction boxes. The maximum cable length between machines or junction boxes is 1000 m. A maximum of 1000 nodes can be connected in a power network. All generators\\, batteries\\, junction boxes and machines count as nodes.\n"..
"Branches can be realized using junction boxes. The maximum cable length between machines or junction boxes is 1000 m. A maximum of 1000 nodes can be connected in a power network. All blocks with power connection\\, including junction boxes\\, count as nodes.\n"..
"\n"..
"Since the power cables are not automatically protected\\, the land lines (TA power line) are recommended for longer distances.\n"..
"\n"..
@ -621,7 +677,6 @@ techage.manual_EN.aText = {
"\n"..
"\n",
"With the junction box\\, electricity can be distributed in up to 6 directions. Junction boxes can also be plastered (hidden) with a trowel and made visible again.\n"..
"If the TechAge Info tool (wrench) is clicked on the junction box\\, it is shown whether the power line is powered or not.\n"..
"\n"..
"\n"..
"\n",
@ -662,17 +717,25 @@ techage.manual_EN.aText = {
"\n"..
"\n",
"The battery block is used to store excess energy and automatically delivers power in the event of a power failure (if available).\n"..
"The battery block is a secondary power source. This means that the generators are used first when electricity is required. The battery block will only provide power if there is insufficient electricity in the network. The same applies to the current consumption. Therefore\\, no battery can be charged with another battery.\n"..
"The battery delivers 10 ku or takes up 10 ku.\n"..
"At full load\\, a battery can take up to 400 s of current and\\, when it is full\\, also release it again. This corresponds to 8 hours of playing time on a normal game day of 20 minutes.\n"..
"Several battery blocks together form a TA3 energy storage system. Each battery block has a display for the charging state and for the stored load.\n"..
"The values for the entire network are always displayed here. The stored load is displayed in \"kud\" or \"ku-days\" (analogous to kWh) 5 kud thus corresponds\\, for example\\, to 5 ku for a game day (20 min) or 1 ku for 5 game days.\n"..
"\n"..
"A battery block has 3.33 kud\n"..
"\n"..
"\n"..
"\n",
"The power terminal must be connected to the power grid. It shows data from the power grid.\n"..
"\n"..
"Only the data of a selected type are output in the upper half. If\\, for example\\, \"Power station\" is selected as the type\\, only the data from oil and coal-fired power stations are collected and output. The data from generators (power delivery) and the data from energy storage devices (power consumption) are output on the left. In the case of the battery blocl\\, for example\\, both are output because the battery can draw and deliver power.\n"..
"The most important figures are displayed in the upper half:\n"..
"\n"..
"In the lower half\\, the data of all generators and storage systems of the entire electricity network are summarized.\n"..
" - current/maximum generator power\n"..
" - current power consumption of all consumers\n"..
" - current charging current in/from the storage system\n"..
" - Current state of charge of the storage system in percent\n"..
"\n"..
"The number of network blocks is output in the lower half.\n"..
"\n"..
"Additional data on the generators and storage systems can be queried via the \"console\" tab.\n"..
"\n"..
"\n"..
"\n",
@ -1101,7 +1164,8 @@ techage.manual_EN.aText = {
"",
"The Techage Info Tool (wrench) has several functions. It shows the time\\, position\\, temperature and biome when an unknown block is clicked on.\n"..
"If you click on a TechAge block with command interface\\, all available data will be shown (see also \"Logic / switching blocks\").\n"..
"In the case of power junction boxes\\, the neighboring network participants (up to 50 meters away) are displayed with a blue cage.\n"..
"\n"..
"With Shift + right click an extended menu can be opened for some blocks. Depending on the block\\, further data can be called up or special settings can be made here. In the case of a generator\\, for example\\, the charging curve/switch-off can be programmed. \n"..
"\n"..
"\n"..
"\n",
@ -1135,9 +1199,7 @@ techage.manual_EN.aText = {
"\n"..
"\n",
"The wind turbine block (rotor) is the heart of the wind turbine. This block must be placed on top of the mast. Ideally at Y = 15\\, then you just stay within a map / forceload block.\n"..
"After the block has been set\\, a check is carried out to determine whether all conditions for the operation of the wind turbine have been met. If all conditions are met\\, the rotor blades (wings) appear automatically when this block is set. Otherwise you will get an error message.\n"..
"\n"..
"The check can be repeated by hitting the block. \n"..
"When you start the turbine\\, all conditions for the operation of the wind turbine are checked. If all conditions are met\\, the rotor blades (wings) appear automatically. Otherwise you will get an error message.\n"..
"\n"..
"\n"..
"\n",
@ -1209,11 +1271,13 @@ techage.manual_EN.aText = {
"\n"..
"\n"..
"\n",
"The thermal energy storage replaces the battery block from TA3.\n"..
"\n"..
"The thermal energy store consists of a concrete shell (concrete blocks) filled with gravel. Three sizes of the storage are possible:\n"..
"\n"..
" - Cover with 5x5x5 concrete blocks\\, filled with 27 gravel\\, storage capacity: 1/2 day at 60 ku\n"..
" - Cover with 7x7x7 concrete blocks\\, filled with 125 gravel\\, storage capacity: 2.5 days at 60 ku\n"..
" - Cover with 9x9x9 concrete blocks\\, filled with 343 gravel\\, storage capacity: 6.5 days at 60 ku\n"..
" - Cover with 5x5x5 concrete blocks\\, filled with 27 gravel\\, storage capacity: 22.5 kud\n"..
" - Cover with 7x7x7 concrete blocks\\, filled with 125 gravel\\, storage capacity: 104 kud\n"..
" - Cover with 9x9x9 concrete blocks\\, filled with 343 gravel\\, storage capacity: 286 kud\n"..
"\n"..
"A window made of an obsidian glass block may be in the concrete shell. This must be placed fairly in the middle of the wall. Through this window you can see whether the storage is loaded more than 80%. In the plan on the right you can see the structure of TA4 heat exchanger consisting of 3 blocks\\, the TA4 turbine and the TA4 generator. Pay attention to the alignment of the heat exchanger (the arrow at block 1 must point to the turbine).\n"..
"\n"..
@ -1221,14 +1285,13 @@ techage.manual_EN.aText = {
"Both the generator and the heat exchanger have a power connection and must be connected to the power grid.\n"..
"\n"..
"In principle\\, the heat storage system works exactly the same as the batteries\\, only with much more storage capacity.\n"..
"The heat accumulator can hold and deliver 60 ku.\n"..
"\n"..
"In order for the heat storage system to work\\, all blocks (also the concrete shell and gravel) must be loaded using a forceload block.\n"..
"\n"..
"\n"..
"\n",
"The heat exchanger consists of 3 parts that must be placed on top of each other\\, with the arrow of the first block pointing towards the turbine. The pipes must be built with the yellow TA4 pipes.\n"..
"The heat exchanger must be connected to the power grid. The heat exchanger charges the energy store again when sufficient electricity is available and the energy storage is less than 95% charged. The heat exchanger takes up 60 ku. \n"..
"The heat exchanger must be connected to the power grid. The energy storage device is recharged via the heat exchanger\\, provided that sufficient electricity is available. \n"..
"\n"..
"\n"..
"\n",
@ -1237,8 +1300,9 @@ techage.manual_EN.aText = {
"\n"..
"\n",
"The generator is used to generate electricity. Therefore\\, the generator must also be connected to the power grid.\n"..
"The generator is part of the energy storage. It is used to generate electricity and thus releases the energy from the energy storage unit. Therefore\\, the generator must also be connected to the power grid.\n"..
"\n"..
"The generator can deliver 60 ku.\n"..
"Important: Both\\, heat exchanger and generator must be connected to the same power grid! \n"..
"\n"..
"\n"..
"\n",
@ -1253,6 +1317,32 @@ techage.manual_EN.aText = {
"\n"..
"\n"..
"\n",
"With the help of power cables and junction boxes\\, power networks of up to 1000 blocks/nodes can be set up. However\\, it should be noted that distribution boxes must also be counted. This means that up to 500 generators/storage systems/machines/lamps can be connected to a power grid.\n"..
"\n"..
"With the help of an isolating transformer and electricity meter\\, networks can be connected to form even larger structures.\n"..
"\n"..
"\n"..
"\n",
"With the help of an isolating transformer\\, two power grids can be connected to form a larger network. The isolation transformer can transmit electricity in both directions.\n"..
"\n"..
"The isolation transformer can transmit up to 100 ku. \n"..
"\n"..
"\n"..
"\n",
"With the help of an electricity meter\\, two electricity networks can be connected to form a larger network. The electricity meter only transmits electricity in one direction (note arrow). The amount of electricity (in kud) is measured and displayed. The amount of electricity can also be queried by a Lua controller using the 'consumption' command.\n"..
"\n"..
"The electricity meter can pass up to 200 ku. \n"..
"\n"..
"\n"..
"\n",
"The TA4 laser is used for wireless power transmission. Two blocks are required for this: TA4 Laser Beam Emitter and TA4 Laser Beam Receiver. There must be an air gap between the two blocks so that the laser beam can be built up from the emitter to the receiver. First the emitter must be placed. This immediately switches on the laser beam and shows possible positions of the receiver. Possible positions for the receiver are also output via a chat message. \n"..
"\n"..
"With the laser\\, distances of up to 96 blocks can be bridged. Once the connection has been established (no current has to flow)\\, this is indicated via the info text of the emitter and also of the receiver. \n"..
"\n"..
"The laser blocks themselves do not require any electricity.\n"..
"\n"..
"\n"..
"\n",
"Electrolysis can be used to split electricity into hydrogen and oxygen. On the other hand\\, hydrogen can be converted back into electricity with oxygen from the air using a fuel cell.\n"..
"This enables current peaks or an excess supply of electricity to be converted into hydrogen and thus stored.\n"..
"\n"..
@ -1269,6 +1359,8 @@ techage.manual_EN.aText = {
"The electrolyzer can draw up to 35 ku of electricity and then generates a hydrogen item every 4 s.\n"..
"200 units of hydrogen fit into the electrolyzer.\n"..
"\n"..
"The electrolyzer has a wrench menu for setting the current consumption and the switch-off point.\n"..
"\n"..
"\n"..
"\n",
"The fuel cell converts hydrogen into electricity.\n"..
@ -1616,20 +1708,14 @@ techage.manual_EN.aText = {
"\n"..
" \n"..
"\n",
"The TA4 laser is used for wireless power transmission. Two blocks are required for this: TA4 Laser Beam Emitter and TA4 Laser Beam Receiver. There must be an air gap between the two blocks so that the laser beam can be built up from the emitter to the receiver. First the emitter must be placed. This immediately switches on the laser beam and shows possible positions of the receiver. Possible positions for the receiver are also output via a chat message. \n"..
"\n"..
"With the laser\\, distances of up to 96 blocks can be bridged. Once the connection has been established (no current has to flow)\\, this is indicated via the info text of the emitter and also of the receiver. \n"..
"\n"..
"The laser blocks themselves do not require any electricity.\n"..
"\n"..
"\n"..
"\n",
}
techage.manual_EN.aItemName = {
"techage_ta4",
"",
"",
"",
"",
"meridium",
"usmium",
"baborium",
@ -1656,6 +1742,9 @@ techage.manual_EN.aItemName = {
"ta2_driveaxle",
"ta2_generator",
"",
"ta2_winch",
"ta2_weight_chest",
"",
"tube",
"concentrator",
"ta2_pusher",
@ -1682,6 +1771,7 @@ techage.manual_EN.aItemName = {
"ta3_generator",
"ta3_cooler",
"ta3_powerswitch",
"power_reduction",
"ta3_powercable",
"ta3_powerjunction",
"ta3_powerline",
@ -1771,6 +1861,10 @@ techage.manual_EN.aItemName = {
"ta4_generator",
"ta4_pipeinlet",
"ta4_pipe",
"ta4_transformer",
"ta4_transformer",
"ta4_electricmeter",
"ta4_laser",
"ta4_hydrogen",
"ta4_electrolyzer",
"ta4_fuelcell",
@ -1822,7 +1916,6 @@ techage.manual_EN.aItemName = {
"ta4_electronicfab",
"ta4_injector",
"ta4_recycler",
"ta4_laser",
}
techage.manual_EN.aPlanTable = {
@ -1837,6 +1930,8 @@ techage.manual_EN.aPlanTable = {
"",
"",
"",
"",
"",
"coalpile",
"coalburner",
"",
@ -1854,6 +1949,9 @@ techage.manual_EN.aPlanTable = {
"",
"",
"",
"ta2_storage",
"",
"",
"itemtransport",
"",
"",
@ -1894,6 +1992,7 @@ techage.manual_EN.aPlanTable = {
"",
"",
"",
"",
"ta3_furnace",
"",
"",
@ -1973,6 +2072,10 @@ techage.manual_EN.aPlanTable = {
"",
"",
"",
"",
"",
"",
"",
"ta4_reactor",
"",
"",
@ -2021,6 +2124,5 @@ techage.manual_EN.aPlanTable = {
"",
"",
"",
"",
}

View File

@ -104,6 +104,29 @@ techage.ConstructionPlans["steamengine"] = {
{false, FIBOX, false, PK090, CYLIN, FLYWH, false},
}
--
-- TA2 Storage
--
local GRBOX = {"techage_filling_ta2.png^techage_axle_gearbox.png^techage_frame_ta2.png", "techage:gearbox"}
local AXL00 = {"techage_axle.png", "techage:axle"}
local AXL90 = {"techage_axle.png^[transformR90", "techage:axle"}
local WINCH = {"techage_filling_ta2.png^techage_appl_winch.png^techage_frame_ta2.png", "techage:ta2_winch"}
local ROPE_ = {"techage_rope_inv.png", "techage:ta2_rope"}
local WCHST = {"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png^techage_weight_side.png", "techage:ta2_weight_chest"}
techage.ConstructionPlans["ta2_storage"] = {
{false, false, false, GRBOX, WINCH, false, SIDEV},
{false, false, false, AXL90, ROPE_, false, false},
{false, false, false, AXL90, ROPE_, false, false},
{false, false, false, AXL90, ROPE_, false, false},
{false, false, false, AXL90, ROPE_, false, false},
{false, false, false, AXL90, ROPE_, false, false},
{false, false, false, AXL90, ROPE_, false, false},
{false, false, false, AXL90, WCHST, false, false},
{false, false, false, AXL90, false, false, false},
{AXL00, AXL00, AXL00, GRBOX, false, false, false},
}
--
-- Item Transport
--

View File

@ -3,137 +3,32 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
TA4 TES Generator
TA4 TES Generator (dummy)
- can be started and stopped
- provides netID of cable network
]]--
-- for lazy programmers
local M = minetest.get_meta
local S = techage.S
local STANDBY_TICKS = 4
local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 2
local PWR_CAPA = 60
local Cable = techage.ElectricCable
local power = techage.power
local networks = techage.networks
local power = networks.power
local function formspec(self, pos, nvm)
return "size[4,4]"..
"box[0,-0.1;3.8,0.5;#c6e8ff]"..
"label[1,-0.1;"..minetest.colorize( "#000000", S("Generator")).."]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
power.formspec_label_bar(pos, 0, 0.8, S("Electricity"), PWR_CAPA, nvm.provided)..
"image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
"tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]"
end
local function transfer_turbine(pos, topic, payload)
return techage.transfer(pos, "L", topic, payload, nil,
{"techage:ta4_turbine", "techage:ta4_turbine_on"})
end
local function can_start(pos, nvm, state)
if (nvm.heatexchanger_trigger or 0) == 0 then -- by means of heatexchanger
return S("storage empty?")
end
return true
end
local function start_node(pos, nvm, state)
local outdir = M(pos):get_int("outdir")
power.generator_start(pos, Cable, CYCLE_TIME, outdir)
transfer_turbine(pos, "start")
nvm.running = true
end
local function stop_node(pos, nvm, state)
local outdir = M(pos):get_int("outdir")
power.generator_stop(pos, Cable, outdir)
nvm.provided = 0
transfer_turbine(pos, "stop")
nvm.running = false
end
local State = techage.NodeStates:new({
node_name_passive = "techage:ta4_generator",
node_name_active = "techage:ta4_generator_on",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
formspec_func = formspec,
infotext_name = S("TA4 Generator"),
can_start = can_start,
start_node = start_node,
stop_node = stop_node,
})
local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos)
nvm.heatexchanger_trigger = (nvm.heatexchanger_trigger or 0) - 1
if nvm.heatexchanger_trigger <= 0 then
State:nopower(pos, nvm)
stop_node(pos, nvm, State)
transfer_turbine(pos, "stop")
else
local outdir = M(pos):get_int("outdir")
nvm.provided = power.generator_alive(pos, Cable, CYCLE_TIME, outdir)
State:keep_running(pos, nvm, COUNTDOWN_TICKS)
end
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
return State:is_active(nvm)
end
local function on_receive_fields(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
local function swap_node(pos, name)
local node = techage.get_node_lvm(pos)
if node.name == name then
return
end
local nvm,_ = techage.get_nvm(pos, true)
State:state_button_event(pos, nvm, fields)
node.name = name
minetest.swap_node(pos, node)
end
local function on_rightclick(pos, node, clicker)
local nvm = techage.get_nvm(pos)
techage.set_activeformspec(pos, clicker)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
local function after_place_node(pos)
local nvm = techage.get_nvm(pos)
local number = techage.add_node(pos, "techage:ta4_generator")
State:node_init(pos, nvm, number)
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
M(pos):set_string("formspec", formspec(State, pos, nvm))
Cable:after_place_node(pos)
end
local function after_dig_node(pos, oldnode)
Cable:after_dig_node(pos)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
end
local net_def = {
ele1 = {
sides = {R = 1},
ntype = "gen2",
nominal = PWR_CAPA,
},
}
minetest.register_node("techage:ta4_generator", {
description = S("TA4 Generator"),
tiles = {
@ -146,13 +41,14 @@ minetest.register_node("techage:ta4_generator", {
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_generator.png^[transformFX]",
},
on_receive_fields = on_receive_fields,
on_rightclick = on_rightclick,
on_timer = node_timer,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
after_place_node = function(pos)
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
Cable:after_place_node(pos)
end,
after_dig_node = function(pos, oldnode)
Cable:after_dig_node(pos)
techage.del_mem(pos)
end,
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
@ -191,16 +87,8 @@ minetest.register_node("techage:ta4_generator_on", {
},
},
on_receive_fields = on_receive_fields,
on_rightclick = on_rightclick,
on_timer = node_timer,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
drop = "",
paramtype2 = "facedir",
drop = "",
groups = {not_in_creative_inventory=1},
diggable = false,
on_rotate = screwdriver.disallow,
@ -208,32 +96,27 @@ minetest.register_node("techage:ta4_generator_on", {
sounds = default.node_sound_wood_defaults(),
})
Cable:add_secondary_node_names({"techage:ta4_generator", "techage:ta4_generator_on"})
-- The generator is a dummy, it only has to network connection to check the netID
power.register_nodes({"techage:ta4_generator", "techage:ta4_generator_on"}, Cable, "con", {"R"})
-- controlled by the turbine
techage.register_node({"techage:ta4_generator", "techage:ta4_generator_on"}, {
on_transfer = function(pos, in_dir, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "trigger" then
--print("trigger", nvm.provided)
nvm.heatexchanger_trigger = 3
if nvm.running then
return nvm.provided or 0.1
else
return 0
end
if topic == "netID" then
local outdir = M(pos):get_int("outdir")
return networks.determine_netID(pos, Cable, outdir)
elseif topic == "start" then
swap_node(pos, "techage:ta4_generator_on")
elseif topic == "stop" then
swap_node(pos, "techage:ta4_generator")
end
end,
on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "delivered" then
return math.floor((nvm.provided or 0) + 0.5)
elseif topic == "load" then
local capa_max, capa = transfer_turbine(pos, "state")
return techage.power.percent(capa_max, capa)
else
return State:on_receive_message(pos, topic, payload)
end
return "unsupported"
end,
on_node_load = function(pos)
-- remove legacy formspec
M(pos):set_string("formspec", "")
end,
})

View File

@ -3,13 +3,14 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
TA4 Heat Exchanger1 (bottom part)
- has a connection to storage and turbine (via pipes)
- acts as a cable junction for Exchanger2
]]--
-- for lazy programmers
@ -18,38 +19,9 @@ local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local CYCLE_TIME = 2
local PWR_PERF = 60
local GRVL_CAPA = 700
local PWR_CAPA = {
[5] = GRVL_CAPA * 3 * 3 * 3, -- 18900 Cyc = 630 min = 31.5 Tage bei einem ku, oder 31,5 * 24 kuh = 756 kuh = 12,6 h bei 60 ku
[7] = GRVL_CAPA * 5 * 5 * 5, -- ~2.5 days
[9] = GRVL_CAPA * 7 * 7 * 7, -- ~6 days
}
local Cable = techage.ElectricCable
local Pipe = techage.LiquidPipe
local power = techage.power
local in_range = techage.in_range
local function swap_node(pos, name)
local node = techage.get_node_lvm(pos)
if node.name == name then
return
end
node.name = name
minetest.swap_node(pos, node)
end
local function glowing(pos, nvm, should_glow)
if nvm.win_pos then
if should_glow then
swap_node(nvm.win_pos, "techage:glow_gravel")
else
swap_node(nvm.win_pos, "default:gravel")
end
end
end
local power = networks.power
local function turbine_cmnd(pos, topic, payload)
return techage.transfer(pos, "R", topic, payload, Pipe,
@ -61,153 +33,6 @@ local function inlet_cmnd(pos, topic, payload)
{"techage:ta4_pipe_inlet"})
end
local function play_sound(pos)
local mem = techage.get_mem(pos)
if not mem.handle or mem.handle == -1 then
mem.handle = minetest.sound_play("techage_booster", {
pos = pos,
gain = 0.3,
max_hear_distance = 10,
loop = true})
if mem.handle == -1 then
minetest.after(1, play_sound, pos)
end
end
local nvm = techage.get_nvm(pos)
nvm.charging = true
end
local function stop_sound(pos)
local mem = techage.get_mem(pos)
if mem.handle then
minetest.sound_stop(mem.handle)
mem.handle = nil
end
local nvm = techage.get_nvm(pos)
nvm.charging = false
end
local function on_power(pos)
end
local function on_nopower(pos)
end
local function is_running(pos, nvm)
return nvm.charging
end
local function start_node(pos, nvm)
nvm.running = true
nvm.needed = 0
nvm.win_pos = inlet_cmnd(pos, "window")
power.consumer_start(pos, Cable, CYCLE_TIME)
minetest.get_node_timer(pos):start(CYCLE_TIME)
return true
end
local function stop_node(pos, nvm)
nvm.running = false
nvm.needed = 0
power.consumer_stop(pos, Cable)
minetest.get_node_timer(pos):stop()
stop_sound(pos)
return true
end
local function after_place_node(pos, placer, itemstack)
local nvm = techage.get_nvm(pos)
nvm.capa = 0
M(pos):set_string("owner", placer:get_player_name())
local number = techage.add_node(pos, "techage:heatexchanger1")
M(pos):set_string("node_number", number)
M(pos):set_string("infotext", S("TA4 Heat Exchanger 1").." "..number)
Cable:after_place_node(pos)
Pipe:after_place_node(pos)
end
local function can_dig(pos, player)
if minetest.is_protected(pos, player:get_player_name()) then
return false
end
local nvm = techage.get_nvm(pos)
return not nvm.running
end
local function after_dig_node(pos, oldnode, oldmetadata, digger)
Cable:after_dig_node(pos)
Pipe:after_dig_node(pos)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
local nvm = techage.get_nvm(pos)
nvm.running = false
end
local function can_start(pos, nvm)
-- the heat exchanger shall be able to start even without
-- having power. Therefore, no "if power.power_available(pos, Cable) then"
local diameter = inlet_cmnd(pos, "diameter")
if diameter then
nvm.capa_max = PWR_CAPA[tonumber(diameter)] or 0
if nvm.capa_max ~= 0 then
local owner = M(pos):get_string("owner") or ""
return inlet_cmnd(pos, "volume", owner)
else
return S("wrong storage diameter")..": "..diameter
end
else
return S("inlet/pipe error")
end
return S("did you check the plan?")
end
local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos)
nvm.capa = nvm.capa or 0
nvm.capa_max = nvm.capa_max or 0
local taken = 0
local given = 0
if nvm.capa < (nvm.capa_max * 0.95) and not nvm.charging then
taken = power.consumer_alive(pos, Cable, CYCLE_TIME)
elseif nvm.capa < nvm.capa_max and nvm.charging then
taken = power.consumer_alive(pos, Cable, CYCLE_TIME)
end
if nvm.capa > 0 then
given = turbine_cmnd(pos, "trigger") or 0
end
if taken > 0 and not nvm.charging then
play_sound(pos)
elseif taken == 0 and nvm.charging then
stop_sound(pos)
end
nvm.needed = taken - given
nvm.capa = in_range(nvm.capa + nvm.needed, 0, nvm.capa_max)
glowing(pos, nvm, nvm.capa > nvm.capa_max * 0.8)
--print("node_timer TES "..P2S(pos), nvm.needed, nvm.capa, nvm.capa_max)
return true
end
local net_def = {
ele1 = {
sides = {F = 1, B = 1},
ntype = "con2",
nominal = PWR_PERF,
on_power = on_power,
on_nopower = on_nopower,
is_running = is_running,
},
pipe2 = {
sides = {L = 1, R = 1},
ntype = "con1",
},
}
minetest.register_node("techage:heatexchanger1", {
description = S("TA4 Heat Exchanger 1"),
tiles = {
@ -220,13 +45,27 @@ minetest.register_node("techage:heatexchanger1", {
"techage_filling_ta4.png^techage_frameB_ta4.png^techage_appl_hole_electric.png",
},
on_timer = node_timer,
after_place_node = after_place_node,
can_dig = can_dig,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
after_place_node = function(pos, placer, itemstack, pointed_thing)
Cable:after_place_node(pos)
Pipe:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
if tlib2 == Cable then
power.update_network(pos, 0, tlib2, node)
end
end,
can_dig = function(pos, player)
if minetest.is_protected(pos, player:get_player_name()) then
return false
end
pos.y = pos.y + 1
return minetest.get_node(pos).name ~= "techage:heatexchanger2"
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Cable:after_dig_node(pos)
Pipe:after_dig_node(pos)
end,
networks = {},
paramtype2 = "facedir",
groups = {crumbly = 2, cracky = 2, snappy = 2},
on_rotate = screwdriver.disallow,
@ -235,62 +74,21 @@ minetest.register_node("techage:heatexchanger1", {
})
Pipe:add_secondary_node_names({"techage:heatexchanger1"})
Cable:add_secondary_node_names({"techage:heatexchanger1"})
Pipe:set_valid_sides("techage:heatexchanger1", {"R", "L"})
power.register_nodes({"techage:heatexchanger1"}, Cable, "junc", {"F", "B", "U"})
-- command interface
techage.register_node({"techage:heatexchanger1"}, {
on_transfer = function(pos, indir, topic, payload)
local nvm = techage.get_nvm(pos)
-- used by heatexchanger2
if topic == "state" then
return (nvm.capa_max or 0), (nvm.capa or 0), PWR_PERF, math.max(nvm.needed or 0, 0)
elseif topic == "integrity" then
return inlet_cmnd(pos, "volume", payload)
elseif topic == "state" then
return inlet_cmnd(pos, "volume", payload)
elseif topic == "can_start" then
return can_start(pos, nvm)
elseif topic == "start" then
return start_node(pos, nvm)
elseif topic == "stop" then
return stop_node(pos, nvm)
end
end,
on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "state" then
if nvm.charging then
return "running"
elseif nvm.running then
return "standby"
else
return "stopped"
end
elseif topic == "delivered" then
return -math.max(nvm.needed or 0, 0)
elseif topic == "load" then
return techage.power.percent(nvm.capa_max, nvm.capa)
elseif topic == "on" then
start_node(pos, techage.get_nvm(pos))
return true
elseif topic == "off" then
stop_node(pos, techage.get_nvm(pos))
return true
if topic == "diameter" or topic == "volume" or topic == "window" then
return inlet_cmnd(pos, topic, payload)
else
return "unsupported"
return turbine_cmnd(pos, topic, payload)
end
end,
on_node_load = function(pos, node)
local nvm = techage.get_nvm(pos)
if nvm.running and nvm.charging then
play_sound(pos)
else
stop_sound(pos)
end
local mem = tubelib2.get_mem(pos)
nvm.capa = (nvm.capa or 0) + (mem.capa or 0)
--tubelib2.del_mem(pos)
end,
})
minetest.register_craft({

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -18,57 +18,137 @@ local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local power = techage.power
local Cable = techage.ElectricCable
local Pipe = techage.LiquidPipe
local power = networks.power
local control = networks.control
local CYCLE_TIME = 2
local GRVL_CAPA = 500
local PWR_CAPA = {
[5] = GRVL_CAPA * 3 * 3 * 3, -- 13500 Cyc = 450 min = 22.5 kud
[7] = GRVL_CAPA * 5 * 5 * 5, -- 104 kud
[9] = GRVL_CAPA * 7 * 7 * 7, -- 286 kuh
}
local DOWN = 5
local function he1_cmnd(pos, topic, payload)
local function heatexchanger1_cmnd(pos, topic, payload)
return techage.transfer({x = pos.x, y = pos.y - 1, z = pos.z},
nil, topic, payload, nil,
{"techage:heatexchanger1"})
end
local function formspec(self, pos, nvm)
local capa_max, capa, needed_max, needed = he1_cmnd(pos, "state")
capa_max = capa_max or 0
capa = capa or 0
needed_max = needed_max or 0
needed = needed or 0
local arrow = "image[2.5,1.5;1,1;techage_form_arrow_bg.png^[transformR270]"
if needed > 0 then
arrow = "image[2.5,1.5;1,1;techage_form_arrow_fg.png^[transformR270]"
local function heatexchanger3_cmnd(pos, topic, payload)
return techage.transfer({x = pos.x, y = pos.y + 1, z = pos.z},
nil, topic, payload, nil,
{"techage:heatexchanger3"})
end
local function swap_node(pos, name)
local node = techage.get_node_lvm(pos)
if node.name == name then
return
end
return "size[6,4]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"box[0,-0.1;5.8,0.5;#c6e8ff]"..
"label[2,-0.1;"..minetest.colorize( "#000000", S("Heat Exchanger")).."]"..
power.formspec_label_bar(pos, 0, 0.8, S("Electricity"), needed_max, needed)..
power.formspec_label_bar(pos, 3.5, 0.8, S("Thermal"), capa_max, capa, "")..
arrow..
"image_button[2.5,3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
"tooltip[2.5,3;1,1;"..self:get_state_tooltip(nvm).."]"
node.name = name
minetest.swap_node(pos, node)
end
local function can_start(pos, nvm, state)
--print("can_start", he1_cmnd(pos, "can_start"))
return he1_cmnd(pos, "can_start") or S("did you check the plan?")
local function play_sound(pos)
local mem = techage.get_mem(pos)
if not mem.handle or mem.handle == -1 then
mem.handle = minetest.sound_play("techage_booster", {
pos = pos,
gain = 0.3,
max_hear_distance = 10,
loop = true})
if mem.handle == -1 then
minetest.after(1, play_sound, pos)
end
end
end
local function start_node(pos, nvm, state)
he1_cmnd(pos, "start")
local function stop_sound(pos)
local mem = techage.get_mem(pos)
if mem.handle then
minetest.sound_stop(mem.handle)
mem.handle = nil
end
end
local function stop_node(pos, nvm, state)
he1_cmnd(pos, "stop")
local function can_start(pos, nvm)
local netID = networks.determine_netID(pos, Cable, DOWN)
if heatexchanger1_cmnd(pos, "netID") ~= netID then
return S("Power network connection error")
end
local diameter = heatexchanger1_cmnd(pos, "diameter")
if diameter then
nvm.capa_max = PWR_CAPA[tonumber(diameter)] or 0
if nvm.capa_max ~= 0 then
nvm.capa = math.min(nvm.capa or 0, nvm.capa_max)
local owner = M(pos):get_string("owner") or ""
return heatexchanger1_cmnd(pos, "volume", owner)
else
return S("wrong storage diameter") .. ": " .. diameter
end
else
return S("inlet/pipe error")
end
return S("did you check the plan?")
end
local function start_node(pos, nvm)
nvm.win_pos = heatexchanger1_cmnd(pos, "window")
power.start_storage_calc(pos, Cable, DOWN)
play_sound(pos)
heatexchanger1_cmnd(pos, "start")
end
local function stop_node(pos, nvm)
power.start_storage_calc(pos, Cable, DOWN)
stop_sound(pos)
heatexchanger1_cmnd(pos, "stop")
end
local function formspec(self, pos, nvm)
local data
if techage.is_running(nvm) then
data = power.get_network_data(pos, Cable, DOWN)
end
return techage.storage_formspec(self, pos, nvm, S("TA4 Heat Exchanger"), data, nvm.capa, nvm.capa_max)
end
local function glowing(pos, nvm, should_glow)
if nvm.win_pos then
if should_glow then
swap_node(nvm.win_pos, "techage:glow_gravel")
else
swap_node(nvm.win_pos, "default:gravel")
end
end
end
local function check_TES_integrity(pos, nvm)
nvm.ticks = (nvm.ticks or 0) + 1
if (nvm.ticks % 100) == 0 then -- not to often
return he1_cmnd(pos, "integrity", "singleplayer")
if (nvm.ticks % 30) == 0 then -- every minute
return heatexchanger1_cmnd(pos, "volume")
end
if (nvm.ticks % 30) == 10 then -- every minute
return heatexchanger3_cmnd(pos, "diameter") ~= nil or S("inlet/pipe error")
end
if (nvm.ticks % 30) == 20 then -- every minute
return heatexchanger3_cmnd(pos, "diameter") ~= nil or S("inlet/pipe error")
end
local netID = networks.determine_netID(pos, Cable, DOWN)
if heatexchanger1_cmnd(pos, "netID") ~= netID then
if nvm.check_once_again then
nvm.check_once_again = false
return true
else
return S("Power network connection error")
end
end
nvm.check_once_again = true
return true
end
@ -88,13 +168,20 @@ local function node_timer(pos, elapsed)
local res = check_TES_integrity(pos, nvm)
if res ~= true then
State:fault(pos, nvm, res)
he1_cmnd(pos, "stop")
heatexchanger1_cmnd(pos, "stop")
power.start_storage_calc(pos, Cable, DOWN)
end
if techage.is_running(nvm) then
local capa = power.get_storage_load(pos, Cable, DOWN, nvm.capa_max) or 0
if capa > 0 then
nvm.capa = capa
end
end
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec(State, pos, nvm))
return true
end
return false
return true
end
local function can_dig(pos, player)
@ -102,25 +189,34 @@ local function can_dig(pos, player)
return false
end
local nvm = techage.get_nvm(pos)
return not nvm.running
return not techage.is_running(nvm)
end
local function on_rightclick(pos, node, clicker)
techage.set_activeformspec(pos, clicker)
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(State, pos, nvm))
minetest.get_node_timer(pos):start(CYCLE_TIME)
end
local function after_place_node(pos, placer)
if techage.orientate_node(pos, "techage:heatexchanger1") then
return true
end
local meta = M(pos)
local nvm = techage.get_nvm(pos)
State:node_init(pos, nvm, "")
M(pos):set_string("formspec", formspec(State, pos, nvm))
local own_num = techage.add_node(pos, "techage:heatexchanger1")
meta:set_string("owner", placer:get_player_name())
meta:set_string("infotext", S("TA4 Heat Exchanger")..": "..own_num)
meta:set_string("formspec", formspec(State, pos, nvm))
Cable:after_place_node(pos, {DOWN})
State:node_init(pos, nvm, own_num)
end
local function after_dig_node(pos, oldnode, oldmetadata, digger)
Cable:after_dig_node(pos)
techage.del_mem(pos)
end
local function on_receive_fields(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
@ -131,6 +227,14 @@ local function on_receive_fields(pos, formname, fields, player)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
local function get_storage_data(pos, outdir, tlib2)
local nvm = techage.get_nvm(pos)
nvm.capa_max = nvm.capa_max or 1
if techage.is_running(nvm) then
return {level = (nvm.capa or 0) / nvm.capa_max, capa = nvm.capa_max}
end
end
-- Middle node with the formspec from the bottom node
minetest.register_node("techage:heatexchanger2", {
description = S("TA4 Heat Exchanger 2"),
@ -154,6 +258,8 @@ minetest.register_node("techage:heatexchanger2", {
on_timer = node_timer,
after_place_node = after_place_node,
can_dig = can_dig,
after_dig_node = after_dig_node,
get_storage_data = get_storage_data,
paramtype2 = "facedir",
groups = {crumbly = 2, cracky = 2, snappy = 2},
@ -162,6 +268,81 @@ minetest.register_node("techage:heatexchanger2", {
sounds = default.node_sound_metal_defaults(),
})
power.register_nodes({"techage:heatexchanger2"}, Cable, "sto", {"D"})
techage.register_node({"techage:heatexchanger2"}, {
on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "state" then
if techage.is_running(nvm) then
return "running"
else
return "stopped"
end
elseif topic == "delivered" then
return -math.max(nvm.needed or 0, 0)
elseif topic == "load" then
return techage.power.percent(nvm.capa_max, nvm.capa)
elseif topic == "on" then
start_node(pos, techage.get_nvm(pos))
return true
elseif topic == "off" then
stop_node(pos, techage.get_nvm(pos))
return true
else
return "unsupported"
end
end,
on_node_load = function(pos, node)
local nvm = techage.get_nvm(pos)
if techage.is_running(nvm) then
play_sound(pos)
else
stop_sound(pos)
end
-- convert to v1
if not nvm.capa_max then
local pos1 = {x = pos.x, y = pos.y - 1, z = pos.z}
local nvm1 = techage.get_nvm(pos1)
nvm.capa_max = nvm1.capa_max or 1
nvm.capa = nvm1.capa or 0
local own_num = techage.add_node(pos, "techage:heatexchanger2")
State:node_init(pos, nvm, own_num)
if nvm1.running then
State:start(pos, nvm)
end
M(pos):set_string("owner", M(pos1):get_string("owner"))
M(pos):set_string("infotext", S("TA4 Heat Exchanger")..": "..own_num)
M(pos1):set_string("node_number", "")
M(pos1):set_string("infotext", "")
techage.del_mem(pos1)
Cable:after_place_node(pos)
Cable:after_place_node(pos1)
end
end,
})
control.register_nodes({"techage:heatexchanger2"}, {
on_receive = function(pos, tlib2, topic, payload)
end,
on_request = function(pos, tlib2, topic)
if topic == "info" then
local nvm = techage.get_nvm(pos)
return {
type = S("TA4 Heat Exchanger"),
number = M(pos):get_string("node_number") or "",
running = techage.is_running(nvm) or false,
capa = nvm.capa_max or 1,
load = nvm.capa or 0,
}
end
return false
end,
}
)
minetest.register_craft({
output = "techage:heatexchanger2",
recipe = {

View File

@ -42,6 +42,11 @@ local function after_dig_node(pos, oldnode)
Pipe:after_dig_node(pos)
end
local function inlet_cmnd(pos, topic, payload)
return techage.transfer(pos, "L", topic, payload, Pipe,
{"techage:ta4_pipe_inlet"})
end
minetest.register_node("techage:heatexchanger3", {
description = S("TA4 Heat Exchanger 3"),
tiles = {
@ -57,6 +62,9 @@ minetest.register_node("techage:heatexchanger3", {
after_place_node = after_place_node,
after_dig_node = after_dig_node,
networks = {
pipe2 = {},
},
paramtype2 = "facedir",
groups = {crumbly = 2, cracky = 2, snappy = 2},
on_rotate = screwdriver.disallow,
@ -66,10 +74,11 @@ minetest.register_node("techage:heatexchanger3", {
Pipe:add_secondary_node_names({"techage:heatexchanger3"})
-- command interface, used by heatexchanger2
techage.register_node({"techage:heatexchanger3"}, {
on_transfer = function(pos, in_dir, topic, payload)
return true
end
on_transfer = function(pos, indir, topic, payload)
return inlet_cmnd(pos, topic, payload)
end,
})
minetest.register_craft({

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -44,6 +44,9 @@ minetest.register_node("techage:ta4_pipe_inlet", {
after_place_node = after_place_node,
after_dig_node = after_dig_node,
networks = {
pipe2 = {},
},
paramtype2 = "facedir", -- important!
on_rotate = screwdriver.disallow, -- important!
groups = {crumbly = 2, cracky = 2, snappy = 2},
@ -66,13 +69,6 @@ local Numbers = {
}
}
local function chat(owner, text)
if owner ~= nil then
minetest.chat_send_player(owner, string.char(0x1b).."(c@#ff0000)".."[Techage] Error: "..text.."!")
end
return text
end
local function get_diameter(pos, in_dir)
local dir = tubelib2.Dir6dToVector[in_dir]
local pos2, node
@ -125,14 +121,14 @@ local function check_volume(pos, in_dir, owner)
"basic_materials:concrete_block", "default:obsidian_glass",
"techage:glow_gravel"})
if node_tbl["default:obsidian_glass"] > 1 then
return chat(owner, "one window maximum")
return S("one window maximum")
elseif node_tbl["default:obsidian_glass"] + node_tbl["basic_materials:concrete_block"] ~= Numbers.shell[radius] then
return chat(owner, "wrong number of shell nodes")
return S("wrong number of shell nodes")
elseif node_tbl["default:gravel"] + node_tbl["techage:glow_gravel"] ~= Numbers.filling[radius] then
return chat(owner, "wrong number of gravel nodes")
return S("wrong number of gravel nodes")
end
else
return chat(owner, "wrong diameter (should be 5, 7, or 9)")
return S("wrong diameter (should be 5, 7, or 9)")
end
return true
end
@ -162,8 +158,6 @@ techage.register_node({"techage:ta4_pipe_inlet"}, {
on_transfer = function(pos, in_dir, topic, payload)
if topic == "diameter" then
return get_diameter(pos, in_dir)
elseif topic == "integrity" then
return check_volume(pos, in_dir, payload)
elseif topic == "volume" then
return check_volume(pos, in_dir, payload)
elseif topic == "window" then

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -18,17 +18,7 @@ local S = techage.S
local Pipe = techage.LiquidPipe
local function transfer_heatexchanger3(pos, topic, payload)
return techage.transfer(pos, 6, topic, payload, Pipe,
{"techage:heatexchanger3"})
end
local function transfer_heatexchanger1(pos, topic, payload)
return techage.transfer(pos, "L", topic, payload, Pipe,
{"techage:heatexchanger1"})
end
local function transfer_generator(pos, topic, payload)
local function generator_cmnd(pos, topic, payload)
return techage.transfer(pos, "R", topic, payload, nil,
{"techage:ta4_generator", "techage:ta4_generator_on"})
end
@ -64,21 +54,6 @@ local function stop_sound(pos)
end
end
local function after_place_node(pos)
Pipe:after_place_node(pos)
end
local function after_dig_node(pos, oldnode)
stop_sound(pos)
Pipe:after_dig_node(pos)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
swap_node(pos, "techage:ta4_turbine")
stop_sound(pos)
end
minetest.register_node("techage:ta4_turbine", {
description = S("TA4 Turbine"),
tiles = {
@ -91,10 +66,17 @@ minetest.register_node("techage:ta4_turbine", {
"techage_filling_ta4.png^techage_appl_turbine.png^techage_frame_ta4.png",
},
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
after_place_node = function(pos)
Pipe:after_place_node(pos)
end,
after_dig_node = function(pos, oldnode)
stop_sound(pos)
Pipe:after_dig_node(pos)
techage.del_mem(pos)
end,
networks = {
pipe2 = {},
},
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
on_rotate = screwdriver.disallow,
@ -131,8 +113,14 @@ minetest.register_node("techage:ta4_turbine_on", {
},
},
tubelib2_on_update2 = tubelib2_on_update2,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
swap_node(pos, "techage:ta4_turbine")
stop_sound(pos)
generator_cmnd(pos, "stop")
end,
networks = {
pipe2 = {},
},
paramtype2 = "facedir",
groups = {not_in_creative_inventory=1},
diggable = false,
@ -142,31 +130,25 @@ minetest.register_node("techage:ta4_turbine_on", {
})
Pipe:add_secondary_node_names({"techage:ta4_turbine", "techage:ta4_turbine_on"})
Pipe:set_valid_sides("techage:ta4_turbine", {"L", "U"})
Pipe:set_valid_sides("techage:ta4_turbine_on", {"L", "U"})
techage.register_node({"techage:ta4_turbine", "techage:ta4_turbine_on"}, {
on_transfer = function(pos, in_dir, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "trigger" then -- used by heatexchanger1
if not transfer_heatexchanger3(pos, topic, payload) then
return 0
end
return transfer_generator(pos, topic, payload)
elseif topic == "start" then -- used by generator
if topic == "start" then -- used by heatexchanger1
swap_node(pos, "techage:ta4_turbine_on")
play_sound(pos)
nvm.running = true
return true
elseif topic == "stop" then -- used by generator
return generator_cmnd(pos, topic, payload)
elseif topic == "stop" then -- used by heatexchanger1
swap_node(pos, "techage:ta4_turbine")
stop_sound(pos)
nvm.running = false
return true
elseif topic == "state" then
return transfer_heatexchanger1(pos, topic, payload)
return generator_cmnd(pos, topic, payload)
else -- used by heatexchanger1
return generator_cmnd(pos, topic, payload)
end
end,
on_node_load = function(pos, node)
--print("on_node_load", node.name)
if node.name == "techage:ta4_turbine_on" then
play_sound(pos)
end

View File

@ -20,8 +20,7 @@ local PWR_NEEDED = 3
local CYCLE_TIME = 2
local Cable = techage.ElectricCable
local power = techage.power
--local networks = techage.networks
local power = networks.power
local function infotext(pos, state)
M(pos):set_string("infotext", S("TA3 Booster")..": "..state)
@ -58,23 +57,6 @@ local function stop_sound(pos)
end
end
local function on_power(pos)
swap_node(pos, "techage:ta3_booster_on")
infotext(pos, "running")
play_sound(pos)
end
local function on_nopower(pos)
swap_node(pos, "techage:ta3_booster")
infotext(pos, "no power")
stop_sound(pos)
end
local function node_timer(pos, elapsed)
power.consumer_alive(pos, Cable, CYCLE_TIME)
return true
end
local function after_place_node(pos)
local nvm = techage.get_nvm(pos)
Cable:after_place_node(pos)
@ -89,10 +71,6 @@ local function after_dig_node(pos, oldnode)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
end
minetest.register_node("techage:ta3_booster", {
description = S("TA3 Booster"),
tiles = {
@ -105,19 +83,17 @@ minetest.register_node("techage:ta3_booster", {
"techage_filling_ta3.png^techage_appl_compressor.png^[transformFX^techage_frame_ta3.png",
},
on_timer = node_timer,
on_timer = function(pos, elapsed)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed == PWR_NEEDED then
swap_node(pos, "techage:ta3_booster_on")
infotext(pos, "running")
play_sound(pos)
end
return true
end,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = {
ele1 = {
sides = {B = true, F = true, L = true, D = true, U = true},
ntype = "con1",
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED,
},
},
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
@ -126,7 +102,6 @@ minetest.register_node("techage:ta3_booster", {
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("techage:ta3_booster_on", {
tiles = {
-- up, down, right, left, back, front
@ -156,20 +131,17 @@ minetest.register_node("techage:ta3_booster_on", {
},
},
on_timer = node_timer,
on_timer = function(pos, elapsed)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed < PWR_NEEDED then
swap_node(pos, "techage:ta3_booster")
infotext(pos, "no power")
stop_sound(pos)
end
return true
end,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = {
ele1 = {
sides = {B = true, F = true, L = true, D = true, U = true},
ntype = "con1",
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED,
is_running = function() return true end,
},
},
paramtype2 = "facedir",
groups = {not_in_creative_inventory = 1},
@ -179,7 +151,7 @@ minetest.register_node("techage:ta3_booster_on", {
sounds = default.node_sound_wood_defaults(),
})
Cable:add_secondary_node_names({"techage:ta3_booster", "techage:ta3_booster_on"})
power.register_nodes({"techage:ta3_booster", "techage:ta3_booster_on"}, Cable, "con", {"B", "F", "L", "D", "U"})
-- for intra machine communication
techage.register_node({"techage:ta3_booster", "techage:ta3_booster_on"}, {
@ -194,15 +166,16 @@ techage.register_node({"techage:ta3_booster", "techage:ta3_booster_on"}, {
elseif topic == "start" and not nvm.running then
if power.power_available(pos, Cable) then
nvm.running = true
power.consumer_start(pos, Cable, CYCLE_TIME)
minetest.get_node_timer(pos):start(CYCLE_TIME)
swap_node(pos, "techage:ta3_booster_on")
infotext(pos, "running")
play_sound(pos)
else
infotext(pos, "no power")
end
elseif topic == "stop" then
nvm.running = false
swap_node(pos, "techage:ta3_booster")
power.consumer_stop(pos, Cable)
minetest.get_node_timer(pos):stop()
infotext(pos, "stopped")
stop_sound(pos)

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -19,7 +19,7 @@ local S = techage.S
local firebox = techage.firebox
local fuel = techage.fuel
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local liquid = networks.liquid
local CYCLE_TIME = 2
local EFFICIENCY = 2 -- burn cycles
@ -80,38 +80,6 @@ local function booster_cmnd(pos, cmnd)
{"techage:ta3_booster", "techage:ta3_booster_on"})
end
local _liquid = {
capa = fuel.CAPACITY,
fuel_cat = fuel.BT_BITUMEN,
peek = liquid.srv_peek,
put = function(pos, indir, name, amount)
if fuel.valid_fuel(name, fuel.BT_BITUMEN) then
local res = liquid.srv_put(pos, indir, name, amount)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", fuel.formspec(nvm))
end
return res
end
return amount
end,
take = function(pos, indir, name, amount)
amount, name = liquid.srv_take(pos, indir, name, amount)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", fuel.formspec(nvm))
end
return amount, name
end
}
local _networks = {
pipe2 = {
sides = techage.networks.AllSides, -- Pipe connection sides
ntype = "tank",
},
}
minetest.register_node("techage:furnace_firebox", {
description = S("TA3 Furnace Oil Burner"),
tiles = {
@ -134,8 +102,6 @@ minetest.register_node("techage:furnace_firebox", {
on_punch = fuel.on_punch,
on_receive_fields = fuel.on_receive_fields,
on_rightclick = fuel.on_rightclick,
liquid = _liquid,
networks = _networks,
on_construct = function(pos)
local nvm = techage.get_nvm(pos)
@ -185,8 +151,6 @@ minetest.register_node("techage:furnace_firebox_on", {
on_receive_fields = fuel.on_receive_fields,
on_punch = fuel.on_punch,
on_rightclick = fuel.on_rightclick,
liquid = _liquid,
networks = _networks,
})
minetest.register_craft({
@ -204,7 +168,7 @@ techage.register_node({"techage:furnace_firebox", "techage:furnace_firebox_on"},
if topic == "state" then
return nvm.running and "running" or "stopped"
elseif topic == "fuel" then
return techage.fuel.get_fuel_amount(nvm)
return fuel.get_fuel_amount(nvm)
else
return "unsupported"
end
@ -237,4 +201,5 @@ techage.register_node({"techage:furnace_firebox", "techage:furnace_firebox_on"},
end,
})
Pipe:add_secondary_node_names({"techage:furnace_firebox", "techage:furnace_firebox_on"})
liquid.register_nodes({"techage:furnace_firebox", "techage:furnace_firebox_on"},
Pipe, "tank", nil, fuel.get_liquid_table(fuel.BT_OIL, fuel.CAPACITY, start_firebox))

View File

@ -16,11 +16,11 @@
local M = minetest.get_meta
local S = techage.S
local CYCLE_TIME = 2
local PWR_NEEDED = 14
local CYCLE_TIME = 2
local Cable = techage.ElectricCable
local power = techage.power
local power = networks.power
local function swap_node(pos, name)
local node = techage.get_node_lvm(pos)
@ -31,18 +31,6 @@ local function swap_node(pos, name)
minetest.swap_node(pos, node)
end
local function on_power(pos)
swap_node(pos, "techage:furnace_heater_on")
end
local function on_nopower(pos)
swap_node(pos, "techage:furnace_heater")
end
local function node_timer(pos, elapsed)
power.consumer_alive(pos, Cable, CYCLE_TIME)
return true
end
local function after_place_node(pos)
Cable:after_place_node(pos)
@ -53,10 +41,6 @@ local function after_dig_node(pos, oldnode)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
end
minetest.register_node("techage:furnace_heater", {
description = S("TA4 Furnace Heater"),
tiles = {
@ -69,19 +53,15 @@ minetest.register_node("techage:furnace_heater", {
"techage_concrete.png^techage_appl_heater.png^techage_frame_ta3.png",
},
on_timer = node_timer,
on_timer = function(pos, elapsed)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed == PWR_NEEDED then
swap_node(pos, "techage:furnace_heater_on")
end
return true
end,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = {
ele1 = {
sides = {B = true, F = true, L = true, D = true, U = true},
ntype = "con1",
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED,
},
},
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
@ -102,20 +82,15 @@ minetest.register_node("techage:furnace_heater_on", {
"techage_concrete.png^techage_appl_heater_on.png^techage_frame_ta3.png",
},
on_timer = node_timer,
on_timer = function(pos, elapsed)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed < PWR_NEEDED then
swap_node(pos, "techage:furnace_heater")
end
return true
end,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = {
ele1 = {
sides = {B = true, F = true, L = true, D = true, U = true},
ntype = "con1",
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED,
is_running = function() return true end,
},
},
light_source = 8,
paramtype2 = "facedir",
@ -126,16 +101,7 @@ minetest.register_node("techage:furnace_heater_on", {
sounds = default.node_sound_wood_defaults(),
})
Cable:add_secondary_node_names({"techage:furnace_heater", "techage:furnace_heater_on"})
minetest.register_craft({
output = "techage:furnace_heater",
recipe = {
{'techage:aluminum', 'default:steel_ingot', 'techage:aluminum'},
{'techage:basalt_stone', 'basic_materials:heating_element', 'techage:basalt_stone'},
{'techage:aluminum', 'techage:ta4_furnace_ceramic', 'techage:aluminum'},
},
})
power.register_nodes({"techage:furnace_heater", "techage:furnace_heater_on"}, Cable, "con", {"B", "F", "L", "D", "U"})
techage.register_node({"techage:furnace_heater", "techage:furnace_heater_on"}, {
-- called from furnace_top
@ -148,16 +114,23 @@ techage.register_node({"techage:furnace_heater", "techage:furnace_heater_on"}, {
elseif topic == "start" and not nvm.running then
if power.power_available(pos, Cable) then
nvm.running = true
power.consumer_start(pos, Cable, CYCLE_TIME)
minetest.get_node_timer(pos):start(CYCLE_TIME)
return true
end
elseif topic == "stop" and nvm.running then
nvm.running = false
swap_node(pos, "techage:furnace_heater")
power.consumer_stop(pos, Cable)
minetest.get_node_timer(pos):stop()
return true
end
end
})
minetest.register_craft({
output = "techage:furnace_heater",
recipe = {
{'techage:aluminum', 'default:steel_ingot', 'techage:aluminum'},
{'techage:basalt_stone', 'basic_materials:heating_element', 'techage:basalt_stone'},
{'techage:aluminum', 'techage:ta4_furnace_ceramic', 'techage:aluminum'},
},
})

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -17,10 +17,9 @@ local M = minetest.get_meta
local S = techage.S
local Cable = techage.ElectricCable
local power = techage.power
local power = networks.power
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local networks = techage.networks
local liquid = networks.liquid
local CYCLE_TIME = 2
local STANDBY_TICKS = 3
@ -28,39 +27,53 @@ local PWR_NEEDED = 35
local PWR_UNITS_PER_HYDROGEN_ITEM = 80
local CAPACITY = 200
local function evaluate_percent(s)
return (tonumber(s:sub(1, -2)) or 0) / 100
end
local function formspec(self, pos, nvm)
local amount = (nvm.liquid and nvm.liquid.amount) or 0
local lqd_name = (nvm.liquid and nvm.liquid.name) or "techage:liquid"
local arrow = "image[3,1.5;1,1;techage_form_arrow_bg.png^[transformR270]"
if nvm.running then
if techage.is_running(nvm) then
arrow = "image[3,1.5;1,1;techage_form_arrow_fg.png^[transformR270]"
end
if amount > 0 then
lqd_name = lqd_name.." "..amount
lqd_name = lqd_name .. " " .. amount
end
return "size[6,4]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"box[0,-0.1;5.8,0.5;#c6e8ff]"..
"label[2.5,-0.1;"..minetest.colorize( "#000000", S("Electrolyzer")).."]"..
techage.power.formspec_label_bar(pos, 0.1, 0.8, S("Electricity"), PWR_NEEDED, nvm.taken)..
arrow..
"image_button[3,2.5;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
"tooltip[3,2.5;1,1;"..self:get_state_tooltip(nvm).."]"..
return "size[6,4]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"box[0,-0.1;5.8,0.5;#c6e8ff]" ..
"label[0.2,-0.1;" .. minetest.colorize( "#000000", S("Electrolyzer")) .. "]" ..
techage.wrench_tooltip(5.4, -0.1)..
techage.formspec_power_bar(pos, 0.1, 0.8, S("Electricity"), nvm.taken, PWR_NEEDED) ..
arrow ..
"image_button[3,2.5;1,1;" .. self:get_state_button_image(nvm) .. ";state_button;]" ..
"tooltip[3,2.5;1,1;" .. self:get_state_tooltip(nvm) .. "]" ..
techage.item_image(4.5,2, lqd_name)
end
local function can_start(pos, nvm, state)
nvm.liquid = nvm.liquid or {}
nvm.liquid.amount = nvm.liquid.amount or 0
if nvm.liquid.amount < CAPACITY then
return true
end
return S("Storage full")
end
local function start_node(pos, nvm, state)
nvm.running = true
nvm.taken = 0
power.consumer_start(pos, Cable, CYCLE_TIME)
nvm.taken = 0
nvm.reduction = evaluate_percent(M(pos):get_string("reduction"))
nvm.turnoff = evaluate_percent(M(pos):get_string("turnoff"))
end
local function stop_node(pos, nvm, state)
nvm.running = false
nvm.taken = 0
power.consumer_stop(pos, Cable)
nvm.running = nil -- legacy
end
local State = techage.NodeStates:new({
@ -70,30 +83,14 @@ local State = techage.NodeStates:new({
standby_ticks = STANDBY_TICKS,
formspec_func = formspec,
infotext_name = S("TA4 Electrolyzer"),
can_start = can_start,
start_node = start_node,
stop_node = stop_node,
})
local function on_power(pos)
local nvm = techage.get_nvm(pos)
State:start(pos, nvm)
nvm.running = true
end
local function on_nopower(pos)
local nvm = techage.get_nvm(pos)
State:stop(pos, nvm)
nvm.running = false
end
local function is_running(pos, nvm)
return nvm.running
end
local function generating(pos, nvm)
nvm.num_pwr_units = nvm.num_pwr_units or 0
nvm.countdown = nvm.countdown or 0
--print("electrolyzer", nvm.running, nvm.taken, nvm.num_pwr_units, nvm.liquid.amount)
if nvm.taken > 0 then
nvm.num_pwr_units = nvm.num_pwr_units + (nvm.taken or 0)
if nvm.num_pwr_units >= PWR_UNITS_PER_HYDROGEN_ITEM then
@ -106,17 +103,33 @@ end
-- converts power into hydrogen
local function node_timer(pos, elapsed)
local meta = M(pos)
local nvm = techage.get_nvm(pos)
nvm.liquid = nvm.liquid or {}
nvm.liquid.amount = nvm.liquid.amount or 0
if nvm.liquid.amount < CAPACITY then
nvm.taken = power.consumer_alive(pos, Cable, CYCLE_TIME)
generating(pos, nvm)
State:keep_running(pos, nvm, 1) -- TODO warum hier 1 und nicht COUNTDOWN_TICKS?
local in_dir = meta:get_int("in_dir")
local curr_load = power.get_storage_load(pos, Cable, in_dir, 1)
if curr_load > (nvm.turnoff or 0) then
local to_be_taken = PWR_NEEDED * (nvm.reduction or 1)
nvm.taken = power.consume_power(pos, Cable, in_dir, to_be_taken) or 0
local running = techage.is_running(nvm)
if not running and nvm.taken == to_be_taken then
State:start(pos, nvm)
elseif running and nvm.taken < to_be_taken then
State:nopower(pos, nvm)
elseif running then
generating(pos, nvm)
State:keep_running(pos, nvm, 1)
end
elseif curr_load == 0 then
State:nopower(pos, nvm)
else
State:standby(pos, nvm, S("Turnoff point reached"))
end
else
State:blocked(pos, nvm, S("full"))
power.consumer_stop(pos, Cable)
State:blocked(pos, nvm, S("Storage full"))
end
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec(State, pos, nvm))
@ -129,6 +142,7 @@ local function on_receive_fields(pos, formname, fields, player)
return
end
local nvm = techage.get_nvm(pos)
techage.set_activeformspec(pos, player)
State:state_button_event(pos, nvm, fields)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
@ -165,44 +179,32 @@ local function put(pos, indir, name, amount)
return leftover
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
if tlib2.tube_type == "pipe2" then
liquid.update_network(pos, outdir, tlib2)
else
power.update_network(pos, outdir, tlib2)
end
end
local netw_def = {
pipe2 = {
sides = {R = 1}, -- Pipe connection sides
ntype = "tank",
local tool_config = {
{
type = "const",
name = "needed",
label = S("Maximum power consumption [ku]"),
tooltip = S("Maximum possible\ncurrent consumption"),
value = PWR_NEEDED,
},
ele1 = {
sides = {L = 1}, -- Cable connection sides
ntype = "con2",
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED,
is_running = is_running,
{
type = "dropdown",
choices = "20%,40%,60%,80%,100%",
name = "reduction",
label = S("Current limitation"),
tooltip = S("Configurable value\nfor the current limit"),
default = "100%",
},
{
type = "dropdown",
choices = "0%,20%,40%,60%,80%",
name = "turnoff",
label = S("Turnoff point"),
tooltip = S("If the charge of the storage\nsystem exceeds the configured value,\nthe block switches off"),
default = "0%",
},
}
local liquid_def = {
capa = CAPACITY,
peek = liquid.srv_peek,
put = put,
untake = put,
take = function(pos, indir, name, amount)
amount, name = liquid.srv_take(pos, indir, name, amount)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
return amount, name
end
}
minetest.register_node("techage:ta4_electrolyzer", {
description = S("TA4 Electrolyzer"),
tiles = {
@ -224,10 +226,7 @@ minetest.register_node("techage:ta4_electrolyzer", {
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
on_punch = liquid.on_punch,
networks = netw_def,
liquid = liquid_def,
on_receive_fields = on_receive_fields,
on_timer = node_timer,
on_rightclick = on_rightclick,
@ -236,6 +235,7 @@ minetest.register_node("techage:ta4_electrolyzer", {
groups = {cracky=2, crumbly=2, choppy=2},
on_rotate = screwdriver.disallow,
is_ground_content = false,
ta3_formspec = tool_config,
})
minetest.register_node("techage:ta4_electrolyzer_on", {
@ -268,9 +268,6 @@ minetest.register_node("techage:ta4_electrolyzer_on", {
},
},
tubelib2_on_update2 = tubelib2_on_update2,
networks = netw_def,
liquid = liquid_def,
on_receive_fields = on_receive_fields,
on_punch = liquid.on_punch,
on_timer = node_timer,
@ -283,10 +280,47 @@ minetest.register_node("techage:ta4_electrolyzer_on", {
diggable = false,
paramtype = "light",
light_source = 6,
ta3_formspec = tool_config,
})
Cable:add_secondary_node_names({"techage:ta4_electrolyzer", "techage:ta4_electrolyzer_on"})
Pipe:add_secondary_node_names({"techage:ta4_electrolyzer", "techage:ta4_electrolyzer_on"})
local liquid_def = {
capa = CAPACITY,
peek = function(pos)
local nvm = techage.get_nvm(pos)
return liquid.srv_peek(nvm)
end,
put = function(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
local leftover = liquid.srv_put(nvm, name, amount, CAPACITY)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
return leftover
end,
take = function(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
amount, name = liquid.srv_take(nvm, name, amount)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
return amount, name
end,
untake = function(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
local leftover = liquid.srv_put(nvm, name, amount, CAPACITY)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
return leftover
end,
}
liquid.register_nodes({"techage:ta4_electrolyzer", "techage:ta4_electrolyzer_on"}, Pipe, "tank", {"R"}, liquid_def)
power.register_nodes({"techage:ta4_electrolyzer", "techage:ta4_electrolyzer_on"}, Cable, "con", {"L"})
techage.register_node({"techage:ta4_electrolyzer", "techage:ta4_electrolyzer_on"}, {
on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
@ -298,6 +332,13 @@ techage.register_node({"techage:ta4_electrolyzer", "techage:ta4_electrolyzer_on"
return State:on_receive_message(pos, topic, payload)
end
end,
on_node_load = function(pos, node)
local meta = M(pos)
if not meta:contains("reduction") then
meta:set_string("reduction", "100%")
meta:set_string("turnoff", "0%")
end
end,
})
minetest.register_craft({

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -17,38 +17,23 @@ local M = minetest.get_meta
local S = techage.S
local Cable = techage.ElectricCable
local power = techage.power
local power = networks.power
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local networks = techage.networks
local liquid = networks.liquid
local control = networks.control
local CYCLE_TIME = 2
local STANDBY_TICKS = 4
local PWR_CAPA = 34
local COUNTDOWN_TICKS = 2
local PWR_PERF = 34
local PWR_UNITS_PER_HYDROGEN_ITEM = 75
local CAPACITY = 100
local States = {}
local STATE = function(pos) return States[techage.get_node_lvm(pos).name] end
local function is_gen1(nvm)
if not nvm.running then
local is_gen1 = dump(nvm.is_gen1 or false)
return "checkbox[0.3,0.5;is_gen1;"..S("Cat. 1 generator")..";"..is_gen1.."]"..
"tooltip[0.3,0.5;1,1;"..S("If set, fuelcell will work\nas cat. 1 generator")..";#0C3D32;#FFFFFF]"
end
if nvm.is_gen1 then
return "label[0.5,0.7;"..S("Cat. 1 generator").."]"
else
return "label[0.5,0.7;"..S("Cat. 2 generator").."]"
end
end
local function formspec(self, pos, nvm)
local amount = (nvm.liquid and nvm.liquid.amount) or 0
local lqd_name = (nvm.liquid and nvm.liquid.name) or "techage:liquid"
local arrow = "image[2,1.5;1,1;techage_form_arrow_bg.png^[transformR270]"
if nvm.running then
if techage.is_running(nvm) then
arrow = "image[2,1.5;1,1;techage_form_arrow_fg.png^[transformR270]"
end
if amount > 0 then
@ -59,40 +44,14 @@ local function formspec(self, pos, nvm)
default.gui_bg_img..
default.gui_slots..
"box[0,-0.1;5.8,0.5;#c6e8ff]"..
"label[2.5,-0.1;"..minetest.colorize( "#000000", S("Fuel Cell")).."]"..
"label[0.2,-0.1;"..minetest.colorize( "#000000", S("Fuel Cell")).."]"..
techage.item_image(0.5,2, lqd_name)..
arrow..
is_gen1(nvm)..
"image_button[2,2.5;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
"tooltip[2,2.5;1,1;"..self:get_state_tooltip(nvm).."]"..
techage.power.formspec_label_bar(pos, 3.5, 0.8, S("Electricity"), PWR_CAPA, nvm.given)
techage.formspec_power_bar(pos, 3.5, 0.8, S("Electricity"), nvm.provided, PWR_PERF)
end
local function start_node(pos, nvm, state)
nvm.running = true
nvm.given = 0
local outdir = M(pos):get_int("outdir")
power.generator_start(pos, Cable, CYCLE_TIME, outdir)
end
local function stop_node(pos, nvm, state)
nvm.running = false
nvm.given = 0
local outdir = M(pos):get_int("outdir")
power.generator_stop(pos, Cable, outdir)
end
local State = techage.NodeStates:new({
node_name_passive = "techage:ta4_fuelcell",
node_name_active = "techage:ta4_fuelcell_on",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
formspec_func = formspec,
infotext_name = S("TA4 Fuel Cell Gen2"),
start_node = start_node,
stop_node = stop_node,
})
local function has_hydrogen(nvm)
nvm.liquid = nvm.liquid or {}
nvm.liquid.amount = nvm.liquid.amount or 0
@ -100,32 +59,76 @@ local function has_hydrogen(nvm)
return nvm.num_pwr_units > 0 or (nvm.liquid.amount > 0 and nvm.liquid.name == "techage:hydrogen")
end
local function can_start(pos, nvm, state)
if has_hydrogen(nvm) then
return true
end
return S("no hydrogen")
end
local function consuming(pos, nvm)
if nvm.num_pwr_units <= 0 then
nvm.num_pwr_units = nvm.num_pwr_units + PWR_UNITS_PER_HYDROGEN_ITEM
nvm.liquid.amount = nvm.liquid.amount - 1
end
nvm.num_pwr_units = nvm.num_pwr_units - nvm.given
nvm.num_pwr_units = nvm.num_pwr_units - nvm.provided
end
-- converts hydrogen into power
local function start_node(pos, nvm, state)
local meta = M(pos)
nvm.provided = 0
local outdir = meta:get_int("outdir")
power.start_storage_calc(pos, Cable, outdir)
techage.evaluate_charge_termination(nvm, meta)
end
local function stop_node(pos, nvm, state)
nvm.provided = 0
nvm.running = nil -- legacy
local outdir = M(pos):get_int("outdir")
power.start_storage_calc(pos, Cable, outdir)
end
local State = techage.NodeStates:new({
node_name_passive = "techage:ta4_fuelcell",
node_name_active = "techage:ta4_fuelcell_on",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
formspec_func = formspec,
infotext_name = S("TA4 Fuel Cell"),
can_start = can_start,
start_node = start_node,
stop_node = stop_node,
})
local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos)
local state = STATE(pos)
--print("fuelcell", nvm.running, nvm.given, nvm.num_pwr_units)
if has_hydrogen(nvm) then
local outdir = M(pos):get_int("outdir")
nvm.given = power.generator_alive(pos, Cable, CYCLE_TIME, outdir)
local running = techage.is_running(nvm)
local hydro = has_hydrogen(nvm)
if running and not hydro then
State:standby(pos, nvm, S("no hydrogen"))
stop_node(pos, nvm, State)
elseif not running and hydro then
State:start(pos, nvm)
-- start_node() is called implicit
elseif running then
local meta = M(pos)
local outdir = meta:get_int("outdir")
local tp1 = tonumber(meta:get_string("termpoint1"))
local tp2 = tonumber(meta:get_string("termpoint2"))
nvm.provided = power.provide_power(pos, Cable, outdir, PWR_PERF, tp1, tp2)
local val = power.get_storage_load(pos, Cable, outdir, PWR_PERF)
if val > 0 then
nvm.load = val
end
consuming(pos, nvm)
state:keep_running(pos, nvm, 1) -- TODO warum hier 1 und nicht COUNTDOWN_TICKS?
else
state:standby(pos, nvm)
nvm.given = 0
State:keep_running(pos, nvm, COUNTDOWN_TICKS)
end
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec(state, pos, nvm))
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
return true
return State:is_active(nvm)
end
local function on_receive_fields(pos, formname, fields, player)
@ -133,36 +136,22 @@ local function on_receive_fields(pos, formname, fields, player)
return
end
local nvm = techage.get_nvm(pos)
if fields.is_gen1 then
nvm.is_gen1 = fields.is_gen1 == "true"
local node = minetest.get_node(pos)
if nvm.is_gen1 then
node.name = "techage:ta4_fuelcell2"
else
node.name = "techage:ta4_fuelcell"
end
minetest.swap_node(pos, node)
local outdir = M(pos):get_int("outdir")
techage.power.update_network(pos, outdir, Cable)
end
STATE(pos):state_button_event(pos, nvm, fields)
M(pos):set_string("formspec", formspec(STATE(pos), pos, nvm))
State:state_button_event(pos, nvm, fields)
end
local function on_rightclick(pos, node, clicker)
local nvm = techage.get_nvm(pos)
techage.set_activeformspec(pos, clicker)
M(pos):set_string("formspec", formspec(STATE(pos), pos, nvm))
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
local function after_place_node(pos)
local nvm = techage.get_nvm(pos)
nvm.running = false
nvm.num_pwr_units = 0
local number = techage.add_node(pos, "techage:ta4_fuelcell")
STATE(pos):node_init(pos, nvm, number)
local node = minetest.get_node(pos)
State:node_init(pos, nvm, number)
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
M(pos):set_string("formspec", formspec(State, pos, nvm))
Pipe:after_place_node(pos)
Cable:after_place_node(pos)
local inv = M(pos):get_inventory()
@ -176,47 +165,13 @@ local function after_dig_node(pos, oldnode, oldmetadata, digger)
Cable:after_dig_node(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
if tlib2.tube_type == "pipe2" then
liquid.update_network(pos, outdir, tlib2)
else
power.update_network(pos, outdir, tlib2)
local function get_generator_data(pos, outdir, tlib2)
local nvm = techage.get_nvm(pos)
if techage.is_running(nvm) then
return {level = (nvm.load or 0) / PWR_PERF, perf = PWR_PERF, capa = PWR_PERF * 2}
end
end
local netw_def = {
pipe2 = {
sides = {L = 1}, -- Pipe connection sides
ntype = "tank",
},
ele1 = {
sides = {R = 1}, -- Cable connection sides
ntype = "gen2",
nominal = PWR_CAPA,
},
}
local liquid_def = {
capa = CAPACITY,
peek = liquid.srv_peek,
put = function(pos, indir, name, amount)
local leftover = liquid.srv_put(pos, indir, name, amount)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(STATE(pos), pos, nvm))
end
return leftover
end,
take = function(pos, indir, name, amount)
amount, name = liquid.srv_take(pos, indir, name, amount)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(STATE(pos), pos, nvm))
end
return amount, name
end
}
minetest.register_node("techage:ta4_fuelcell", {
description = S("TA4 Fuel Cell"),
tiles = {
@ -238,13 +193,12 @@ minetest.register_node("techage:ta4_fuelcell", {
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
get_generator_data = get_generator_data,
on_punch = liquid.on_punch,
networks = netw_def,
liquid = liquid_def,
on_receive_fields = on_receive_fields,
on_timer = node_timer,
on_rightclick = on_rightclick,
ta4_formspec = techage.generator_settings("ta4", PWR_PERF),
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
@ -282,13 +236,12 @@ minetest.register_node("techage:ta4_fuelcell_on", {
},
},
tubelib2_on_update2 = tubelib2_on_update2,
networks = netw_def,
liquid = liquid_def,
get_generator_data = get_generator_data,
on_receive_fields = on_receive_fields,
on_punch = liquid.on_punch,
on_timer = node_timer,
on_rightclick = on_rightclick,
ta4_formspec = techage.generator_settings("ta4", PWR_PERF),
paramtype2 = "facedir",
groups = {not_in_creative_inventory=1},
@ -299,138 +252,81 @@ minetest.register_node("techage:ta4_fuelcell_on", {
light_source = 6,
})
-------------------------------------------------------------------------------
-- Gen1 fuellcell
-------------------------------------------------------------------------------
local State2 = techage.NodeStates:new({
node_name_passive = "techage:ta4_fuelcell2",
node_name_active = "techage:ta4_fuelcell2_on",
cycle_time = CYCLE_TIME,
standby_ticks = STANDBY_TICKS,
formspec_func = formspec,
infotext_name = S("TA4 Fuel Cell Gen1"),
start_node = start_node,
stop_node = stop_node,
})
local netw_def2 = {
pipe2 = {
sides = {L = 1}, -- Pipe connection sides
ntype = "tank",
},
ele1 = {
sides = {R = 1}, -- Cable connection sides
ntype = "gen1",
nominal = PWR_CAPA - 1, -- to be able to distiguish between cat1 and 2
},
local liquid_def = {
capa = CAPACITY,
peek = function(pos)
local nvm = techage.get_nvm(pos)
return liquid.srv_peek(nvm)
end,
put = function(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
local leftover = liquid.srv_put(nvm, name, amount, CAPACITY)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
return leftover
end,
take = function(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
amount, name = liquid.srv_take(nvm, name, amount)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
return amount, name
end,
untake = function(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
local leftover = liquid.srv_put(nvm, name, amount, CAPACITY)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
return leftover
end,
}
minetest.register_node("techage:ta4_fuelcell2", {
description = S("TA4 Fuel Cell"),
tiles = {
-- up, down, right, left, back, front
"techage_filling_ta4.png^techage_frame_ta4_top.png^techage_appl_arrow.png",
"techage_filling_ta4.png^techage_frame_ta4.png",
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_hole_electric.png",
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_hole_pipe.png",
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_fuelcell.png^techage_appl_ctrl_unit.png^[transformFX",
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_fuelcell.png^techage_appl_ctrl_unit.png",
},
liquid.register_nodes({"techage:ta4_fuelcell", "techage:ta4_fuelcell_on"}, Pipe, "tank", {"L"}, liquid_def)
power.register_nodes({"techage:ta4_fuelcell", "techage:ta4_fuelcell_on"}, Cable, "gen", {"R"})
can_dig = function(pos, player)
if minetest.is_protected(pos, player:get_player_name()) then
return false
end
return liquid.is_empty(pos)
end,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
on_punch = liquid.on_punch,
networks = netw_def2,
liquid = liquid_def,
on_receive_fields = on_receive_fields,
on_timer = node_timer,
on_rightclick = on_rightclick,
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2, not_in_creative_inventory=1},
on_rotate = screwdriver.disallow,
is_ground_content = false,
drop = "techage:ta4_fuelcell",
})
minetest.register_alias_force("techage:ta4_fuelcell2", "techage:ta4_fuelcell")
minetest.register_alias_force("techage:ta4_fuelcell2_on", "techage:ta4_fuelcell_on")
minetest.register_node("techage:ta4_fuelcell2_on", {
description = S("TA4 Fuel Cell"),
tiles = {
-- up, down, right, left, back, front
"techage_filling_ta4.png^techage_frame_ta4_top.png^techage_appl_arrow.png",
"techage_filling_ta4.png^techage_frame_ta4.png",
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_hole_electric.png",
"techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_hole_pipe.png",
{
image = "techage_filling4_ta4.png^techage_frame4_ta4.png^techage_appl_fuelcell4.png^techage_appl_ctrl_unit4.png^[transformFX",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 0.8,
},
},
{
image = "techage_filling4_ta4.png^techage_frame4_ta4.png^techage_appl_fuelcell4.png^techage_appl_ctrl_unit4.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 0.8,
},
},
},
tubelib2_on_update2 = tubelib2_on_update2,
networks = netw_def2,
liquid = liquid_def,
on_receive_fields = on_receive_fields,
on_punch = liquid.on_punch,
on_timer = node_timer,
on_rightclick = on_rightclick,
paramtype2 = "facedir",
groups = {not_in_creative_inventory=1},
on_rotate = screwdriver.disallow,
is_ground_content = false,
diggable = false,
paramtype = "light",
light_source = 6,
})
States["techage:ta4_fuelcell"] = State
States["techage:ta4_fuelcell_on"] = State
States["techage:ta4_fuelcell2"] = State2
States["techage:ta4_fuelcell2_on"] = State2
Cable:add_secondary_node_names({"techage:ta4_fuelcell", "techage:ta4_fuelcell_on",
"techage:ta4_fuelcell2", "techage:ta4_fuelcell2_on"})
Pipe:add_secondary_node_names({"techage:ta4_fuelcell", "techage:ta4_fuelcell_on",
"techage:ta4_fuelcell2", "techage:ta4_fuelcell2_on"})
techage.register_node({"techage:ta4_fuelcell", "techage:ta4_fuelcell_on",
"techage:ta4_fuelcell2", "techage:ta4_fuelcell2_on"}, {
techage.register_node({"techage:ta4_fuelcell", "techage:ta4_fuelcell_on"}, {
on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "load" then
return techage.power.percent(CAPACITY, (nvm.liquid and nvm.liquid.amount) or 0)
elseif topic == "delivered" then
return math.floor((nvm.given or 0) + 0.5)
return math.floor((nvm.provided or 0) + 0.5)
else
return STATE(pos):on_receive_message(pos, topic, payload)
return State:on_receive_message(pos, topic, payload)
end
end,
})
control.register_nodes({"techage:ta4_fuelcell", "techage:ta4_fuelcell_on"}, {
on_receive = function(pos, tlib2, topic, payload)
end,
on_request = function(pos, tlib2, topic)
if topic == "info" then
local nvm = techage.get_nvm(pos)
local meta = M(pos)
return {
type = S("TA4 Fuel Cell"),
number = meta:get_string("node_number") or "",
running = techage.is_running(nvm) or false,
available = PWR_PERF,
provided = nvm.provided or 0,
termpoint = meta:get_string("termpoint"),
}
end
return false
end,
}
)
minetest.register_craft({
output = "techage:ta4_fuelcell",
recipe = {

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -13,7 +13,7 @@
techage = {}
-- Version for compatibility checks, see readme.md/history
techage.version = 0.26
techage.version = 1.00
if minetest.global_exists("tubelib") then
minetest.log("error", "[techage] Techage can't be used together with the mod tubelib!")
@ -36,6 +36,9 @@ elseif minetest.global_exists("lcdlib") and lcdlib.version < 1.0 then
elseif minetest.global_exists("safer_lua") and safer_lua.version < 1.0 then
minetest.log("error", "[techage] Techage requires safer_lua version 1.0 or newer!")
return
elseif minetest.global_exists("networks") and networks.version < 0.08 then
minetest.log("error", "[techage] Techage requires networks version 0.08 or newer!")
return
end
-- Test MT 5.4 new string mode
@ -45,7 +48,7 @@ techage.BLEND = minetest.features.use_texture_alpha_string_modes and "blend" or
techage.NodeDef = {} -- node registration info
techage.max_num_forceload_blocks = tonumber(minetest.settings:get("techage_max_num_forceload_blocks")) or 24
techage.basalt_stone_enabled = minetest.settings:get_bool("techage_basalt_stone_enabled") ~= false
techage.ore_rarity = tonumber(minetest.settings:get("techage_ore_rarity")) or 1
techage.modified_recipes_enabled = minetest.settings:get_bool("techage_modified_recipes_enabled") ~= false
@ -85,11 +88,11 @@ dofile(MP.."/basis/fuel_lib.lua") -- common fuel functions
dofile(MP.."/basis/mark.lua")
dofile(MP.."/basis/mark2.lua")
dofile(MP.."/basis/assemble.lua")
dofile(MP.."/basis/networks.lua")
dofile(MP.."/basis/recipe_lib.lua")
dofile(MP.."/basis/formspec_update.lua")
dofile(MP.."/basis/windturbine_lib.lua")
dofile(MP.."/basis/laser_lib.lua")
dofile(MP.."/basis/legacy.lua")
-- Main doc
dofile(MP.."/doc/manual_DE.lua")
@ -99,11 +102,9 @@ dofile(MP.."/doc/items.lua")
dofile(MP.."/doc/guide.lua") -- construction guides
dofile(MP.."/doc/manual_api.lua") -- external API
dofile(MP.."/items/filling.lua")
-- Power networks
dofile(MP.."/power/node_api.lua")
dofile(MP.."/power/junction.lua")
dofile(MP.."/power/distribution.lua")
dofile(MP.."/power/schedule.lua")
dofile(MP.."/power/formspecs.lua")
dofile(MP.."/power/drive_axle.lua")
dofile(MP.."/power/gearbox.lua")
@ -112,13 +113,13 @@ dofile(MP.."/power/electric_cable.lua")
dofile(MP.."/power/junctionbox.lua")
dofile(MP.."/power/power_terminal.lua")
dofile(MP.."/power/power_terminal2.lua")
dofile(MP.."/power/powerswitchbox_legacy.lua")
dofile(MP.."/power/powerswitchbox.lua")
dofile(MP.."/power/powerswitch.lua")
dofile(MP.."/power/protection.lua")
dofile(MP.."/power/power_line.lua")
dofile(MP.."/power/ta4_cable.lua")
dofile(MP.."/power/ta4_cable_wall_entry.lua")
dofile(MP.."/power/laser.lua")
-- Iron Age
dofile(MP.."/iron_age/main.lua")
@ -143,17 +144,21 @@ dofile(MP.."/steam_engine/boiler.lua")
dofile(MP.."/steam_engine/cylinder.lua")
dofile(MP.."/steam_engine/flywheel.lua")
-- TA2 gravity-based energy storage
dofile(MP.."/ta2_energy_storage/ta2_rope.lua")
dofile(MP.."/ta2_energy_storage/ta2_winch.lua")
dofile(MP.."/ta2_energy_storage/ta2_weight_chest.lua")
-- Liquids I
dofile(MP.."/liquids/liquid_pipe.lua")
dofile(MP.."/liquids/valve.lua")
dofile(MP.."/liquids/node_api.lua")
dofile(MP.."/liquids/pipe_wall_entry.lua")
-- Basic Machines
dofile(MP.."/basic_machines/consumer.lua") -- consumer base model
dofile(MP.."/basic_machines/source.lua")
dofile(MP.."/basic_machines/pusher.lua")
dofile(MP.."/basic_machines/legacy_nodes.lua")
dofile(MP.."/basic_machines/foreign_nodes.lua")
dofile(MP.."/basic_machines/mods_support.lua")
dofile(MP.."/basic_machines/grinder.lua")
dofile(MP.."/basic_machines/distributor.lua")
@ -231,6 +236,11 @@ dofile(MP.."/ta3_power/akkubox.lua")
dofile(MP.."/ta3_power/axle2power.lua")
dofile(MP.."/ta3_power/power2axle.lua")
-- TA4 power based
dofile(MP.."/ta4_power/laser.lua")
dofile(MP.."/ta4_power/transformer.lua")
dofile(MP.."/ta4_power/electricmeter.lua")
-- Digtron
if minetest.global_exists("digtron") then
dofile(MP.."/digtron/battery.lua")
@ -263,7 +273,6 @@ end
-- Test
dofile(MP.."/recipe_checker.lua")
dofile(MP.."/.test/sink.lua")
--dofile(MP.."/.test/meta_node.lua")
-- Solar
dofile(MP.."/solar/minicell.lua")
@ -345,3 +354,6 @@ dofile(MP.."/carts/chest_cart.lua")
-- Prevent other mods from using IE
techage.IE = nil
function techage.icta_register_condition(key, tData) end

View File

@ -61,14 +61,14 @@ minetest.register_node("techage:basalt_stone_block", {
minetest.register_node("techage:basalt_gravel", {
description = S("Basalt Gravel"),
tiles = {"default_gravel.png^[brighten"},
groups = {crumbly = 2, falling_node = 1},
groups = {crumbly = 2, falling_node = 1, gravel = 1},
sounds = default.node_sound_gravel_defaults(),
})
minetest.register_node("techage:sieved_basalt_gravel", {
description = S("Sieved Basalt Gravel"),
tiles = {"default_gravel.png^[brighten"},
groups = {crumbly = 2, falling_node = 1, not_in_creative_inventory=1},
groups = {crumbly = 2, falling_node = 1, gravel = 1, not_in_creative_inventory=1},
sounds = default.node_sound_gravel_defaults(),
})

14
items/filling.lua Normal file
View File

@ -0,0 +1,14 @@
-- Needed for the trowel
local fillings = {}
minetest.register_on_mods_loaded(function()
for name, ndef in pairs(minetest.registered_nodes) do
-- test if it is a simple node without logic
if ndef and not ndef.groups.soil and name ~= "default:cobble" and
not ndef.after_place_node and not ndef.on_construct then
table.insert(fillings, name)
end
end
networks.register_filling_items(fillings)
end)

View File

@ -37,3 +37,4 @@ minetest.register_on_mods_loaded(function()
end
end)
minetest.override_item("default:gravel", {groups = {crumbly = 2, gravel = 1, falling_node = 1}})

View File

@ -16,8 +16,10 @@ local S = techage.S
local CYCLE_TIME = 2
local RANDOM_VAL = 20
local PWR_NEEDED = 1
local Cable = techage.ElectricCable
local power = techage.power
local power = networks.power
local Flowers = {}
local Plants = {}
local Ignore = { ["flowers:waterlily_waving"] = true }
@ -34,8 +36,30 @@ local Positions = {
{x = 1, y =-1, z =-1},
}
local function node_timer(pos, elapsed)
power.consumer_alive(pos, Cable, CYCLE_TIME)
local function swap_node(pos, postfix)
local node = techage.get_node_lvm(pos)
local parts = string.split(node.name, "_")
if postfix == parts[2] then
return
end
node.name = parts[1].."_"..postfix
minetest.swap_node(pos, node)
techage.light_ring(pos, postfix == "on")
end
local function on_nopower(pos)
swap_node(pos, "off")
local nvm = techage.get_nvm(pos)
nvm.turned_on = false
end
local function on_power(pos)
swap_node(pos, "on")
local nvm = techage.get_nvm(pos)
nvm.turned_on = true
end
local function grow_flowers(pos)
local nvm = techage.get_nvm(pos)
local mem = techage.get_mem(pos)
mem.grow_pos = mem.grow_pos or {} -- keep the pos blank for some time
@ -67,6 +91,22 @@ local function node_timer(pos, elapsed)
end
end
end
end
local function node_timer_on(pos, elapsed)
grow_flowers(pos)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed < PWR_NEEDED then
on_nopower(pos)
end
return true
end
local function node_timer_off(pos, elapsed)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed == PWR_NEEDED then
on_power(pos)
end
return true
end
@ -95,7 +135,6 @@ techage.register_lamp("techage:growlight", {
{-8/16, -8/16, -8/16, 8/16, -13/32, 8/16},
},
},
on_switch_lamp = on_switch_lamp,
high_power = true,
},{
description = S("TA4 LED Grow Light"),
@ -116,8 +155,7 @@ techage.register_lamp("techage:growlight", {
{-8/16, -8/16, -8/16, 8/16, -13/32, 8/16},
},
},
on_timer = node_timer,
on_switch_lamp = on_switch_lamp,
on_timer = node_timer_on,
high_power = true,
})

View File

@ -21,7 +21,7 @@ local PWR_NEEDED = 0.5
local CYCLE_TIME = 2
local Cable = techage.ElectricCable
local power = techage.power
local power = networks.power
local function swap_node(pos, postfix)
local node = techage.get_node_lvm(pos)
@ -53,8 +53,35 @@ local function is_running(pos, nvm)
return nvm.turned_on
end
local function node_timer(pos, elapsed)
power.consumer_alive(pos, Cable, CYCLE_TIME)
local function node_timer_off1(pos, elapsed)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed == PWR_NEEDED then
on_power(pos)
end
return true
end
local function node_timer_off2(pos, elapsed)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED * 2)
if consumed == PWR_NEEDED * 2 then
on_power(pos)
end
return true
end
local function node_timer_on1(pos, elapsed)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed < PWR_NEEDED then
on_nopower(pos)
end
return true
end
local function node_timer_on2(pos, elapsed)
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED * 2)
if consumed < PWR_NEEDED * 2 then
on_nopower(pos)
end
return true
end
@ -66,12 +93,10 @@ local function lamp_on_rightclick(pos, node, clicker)
local nvm = techage.get_nvm(pos)
if not nvm.turned_on and power.power_available(pos, Cable) then
nvm.turned_on = true
power.consumer_start(pos, Cable, CYCLE_TIME)
minetest.get_node_timer(pos):start(CYCLE_TIME)
swap_node(pos, "on")
else
nvm.turned_on = false
power.consumer_stop(pos, Cable)
minetest.get_node_timer(pos):stop()
swap_node(pos, "off")
end
@ -107,44 +132,19 @@ local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
end
local net_def = {
ele1 = {
sides = {U=1, D=1, L=1, R=1, F=1, B=1}, -- Cable connection sides
ntype = "con1",
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED,
is_running = is_running,
},
}
local net_def2 = {
ele1 = {
sides = {U=1, D=1, L=1, R=1, F=1, B=1}, -- Cable connection sides
ntype = "con1",
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED * 2,
is_running = is_running,
},
}
function techage.register_lamp(basename, ndef_off, ndef_on)
if ndef_off.high_power then
ndef_off.on_timer = ndef_off.on_timer or node_timer_off2
else
ndef_off.on_timer = ndef_off.on_timer or node_timer_off1
end
ndef_off.after_place_node = after_place_node
ndef_off.after_dig_node = after_dig_node
ndef_off.tubelib2_on_update2 = tubelib2_on_update2
if ndef_off.high_power then
ndef_off.networks = net_def2
else
ndef_off.networks = net_def
end
ndef_off.on_rightclick = lamp_on_rightclick
if not ndef_off.on_rotate then
ndef_off.on_place = on_place
end
ndef_off.on_rotate = ndef_off.on_rotate or on_rotate
ndef_off.on_timer = node_timer
ndef_off.paramtype = "light"
ndef_off.use_texture_alpha = techage.CLIP
ndef_off.light_source = 0
@ -154,17 +154,15 @@ function techage.register_lamp(basename, ndef_off, ndef_on)
ndef_off.is_ground_content = false
ndef_off.sounds = default.node_sound_glass_defaults()
if ndef_on.high_power then
ndef_on.on_timer = ndef_on.on_timer or node_timer_on2
else
ndef_on.on_timer = ndef_on.on_timer or node_timer_on1
end
ndef_on.after_place_node = after_place_node
ndef_on.after_dig_node = after_dig_node
ndef_on.tubelib2_on_update2 = tubelib2_on_update2
if ndef_on.high_power then
ndef_on.networks = net_def2
else
ndef_on.networks = net_def
end
ndef_on.on_rightclick = lamp_on_rightclick
ndef_on.on_rotate = ndef_on.on_rotate or on_rotate
ndef_on.on_timer = ndef_on.on_timer or node_timer
ndef_on.paramtype = "light"
ndef_on.use_texture_alpha = techage.CLIP
ndef_on.light_source = minetest.LIGHT_MAX
@ -178,6 +176,9 @@ function techage.register_lamp(basename, ndef_off, ndef_on)
minetest.register_node(basename.."_off", ndef_off)
minetest.register_node(basename.."_on", ndef_on)
Cable:add_secondary_node_names({basename.."_off", basename.."_on"})
power.register_nodes({basename.."_off", basename.."_on"}, Cable, "con")
techage.register_node_for_v1_transition({basename.."_off", basename.."_on"}, function(pos, node)
power.update_network(pos, nil, Cable)
end)
end

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -19,7 +19,8 @@ local M = minetest.get_meta
local S = techage.S
local MAX_PIPE_LENGHT = 100
local networks = techage.networks
local power = networks.power
local Pipe = tubelib2.Tube:new({
dirs_to_check = {1,2,3,4,5,6},
@ -31,7 +32,7 @@ local Pipe = tubelib2.Tube:new({
"techage:ta3_pipeS", "techage:ta3_pipeA",
"techage:ta3_pipe_wall_entry", "techage:ta3_valve_open",
},
secondary_node_names = {"techage:ta3_valve_closed"},
secondary_node_names = {},
after_place_tube = function(pos, param2, tube_type, num_tubes)
local name = minetest.get_node(pos).name
if name == "techage:ta3_pipe_wall_entry" then
@ -44,6 +45,11 @@ local Pipe = tubelib2.Tube:new({
end,
})
-- Use global callback instead of node related functions
Pipe:register_on_tube_update2(function(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2, node)
end)
minetest.register_node("techage:ta3_pipeS", {
description = S("TA Pipe"),
tiles = {
@ -150,33 +156,31 @@ local Boxes = {
}
}
techage.register_junction("techage:ta3_junctionpipe", 1/8, Boxes, Pipe, {
local names = networks.register_junction("techage:ta3_junctionpipe", 1/8, Boxes, Pipe, {
description = S("TA Junction Pipe"),
tiles = {"techage_gaspipe_junction.png"},
use_texture_alpha = "clip",
is_ground_content = false,
groups = {crumbly = 2, cracky = 2, snappy = 2, techage_trowel = 1},
sounds = default.node_sound_metal_defaults(),
after_place_node = function(pos, placer, itemstack, pointed_thing)
local name = "techage:ta3_junctionpipe"..techage.junction_type(pos, Pipe)
local name = "techage:ta3_junctionpipe" .. networks.junction_type(pos, Pipe)
minetest.swap_node(pos, {name = name, param2 = 0})
Pipe:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, dir1, tlib2, node)
local name = "techage:ta3_junctionpipe"..techage.junction_type(pos, Pipe)
local name = "techage:ta3_junctionpipe" .. networks.junction_type(pos, Pipe)
minetest.swap_node(pos, {name = name, param2 = 0})
techage.liquid.update_network(pos)
power.update_network(pos, 0, tlib2, node)
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
end,
networks = {
pipe2 = {
sides = networks.AllSides, -- connection sides for pipes
ntype = "junc",
},
},
}, 25)
power.register_nodes(names, Pipe, "junc")
minetest.register_craft({
output = "techage:ta3_junctionpipe25 2",
recipe = {

View File

@ -1,245 +0,0 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
Liquid transportation API via Pipe(s) (peer, put, take)
]]--
local P2S = minetest.pos_to_string
local M = minetest.get_meta
local N = function(pos) return minetest.get_node(pos).name end
local LQD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).liquid end
local Pipe = techage.LiquidPipe
local S = techage.S
local net_def = techage.networks.net_def
local networks = techage.networks
local liquid = techage.liquid
--
-- Networks
--
-- determine network ID (largest hash number of all pumps)
local function determine_netID(pos, outdir)
local netID = 0
networks.connection_walk(pos, outdir, Pipe, function(pos, indir, node)
local ntype = net_def(pos, "pipe2").ntype
if ntype and ntype == "pump" then
local new = minetest.hash_node_position(pos) * 8 + outdir
if netID <= new then
netID = new
end
end
end)
return netID
end
-- store network ID on each pump like node
local function store_netID(pos, outdir, netID)
networks.connection_walk(pos, outdir, Pipe, function(pos, indir, node)
local ntype = net_def(pos, "pipe2").ntype
if ntype and ntype == "pump" then
local nvm = techage.get_nvm(pos)
local outdir = networks.Flip[indir]
nvm.pipe2 = nvm.pipe2 or {}
nvm.pipe2.netIDs = nvm.pipe2.netIDs or {}
nvm.pipe2.netIDs[outdir] = netID
end
end)
end
-- delete network and ID on each pump like node
local function delete_netID(pos, outdir)
local netID = 0
networks.connection_walk(pos, outdir, Pipe, function(pos, indir, node)
local ntype = net_def(pos, "pipe2").ntype
if ntype and ntype == "pump" then
local nvm = techage.get_nvm(pos)
local outdir = networks.Flip[indir]
if nvm.pipe2 and nvm.pipe2.netIDs and nvm.pipe2.netIDs[outdir] then
netID = nvm.pipe2.netIDs[outdir]
nvm.pipe2.netIDs[outdir] = nil
end
end
end)
networks.delete_network("pipe2", netID)
end
local function get_netID(pos, outdir)
local nvm = techage.get_nvm(pos)
if not nvm.pipe2 or not nvm.pipe2.netIDs or not nvm.pipe2.netIDs[outdir] then
local netID = determine_netID(pos, outdir)
store_netID(pos, outdir, netID)
end
return nvm.pipe2 and nvm.pipe2.netIDs and nvm.pipe2.netIDs[outdir]
end
-- return list of nodes {pos = ..., indir = ...} of given type
local function get_network_table(pos, outdir, ntype)
local netID = get_netID(pos, outdir)
if netID then
local netw = networks.get_network("pipe2", netID)
if not netw then
netw = networks.collect_network_nodes(pos, outdir, Pipe)
networks.set_network("pipe2", netID, netw)
end
if not netw[ntype] then -- connection lost (e.g. tank cart)?
-- reactivate network
networks.node_connections(pos, Pipe)
delete_netID(pos, outdir)
end
--print("netw", string.format("%012X", netID), dump(netw[ntype]))
return netw[ntype] or {}
end
return {}
end
--
-- Client remote functions
--
-- Determine and return liquid 'name' from the
-- remote inventory.
function liquid.peek(pos, outdir)
for _,item in ipairs(get_network_table(pos, outdir, "tank")) do
local liq = LQD(item.pos)
if liq and liq.peek then
return liq.peek(item.pos, item.indir)
end
end
end
-- Add given amount of liquid to the remote inventory.
-- return leftover amount
function liquid.put(pos, outdir, name, amount, player_name)
for _,item in ipairs(get_network_table(pos, outdir, "tank")) do
local liq = LQD(item.pos)
if liq and liq.put and liq.peek then
-- wrong items?
local peek = liq.peek(item.pos, item.indir)
if peek and peek ~= name then return amount or 0 end
if player_name then
local num = techage.get_node_number(pos) or "000"
techage.mark_position(player_name, item.pos, "("..num..") put", "", 1)
end
amount = liq.put(item.pos, item.indir, name, amount)
if not amount or amount == 0 then break end
end
end
return amount or 0
end
-- Take given amount of liquid from the remote inventory.
-- return taken amount and item name
function liquid.take(pos, outdir, name, amount, player_name)
local taken = 0
for _,item in ipairs(get_network_table(pos, outdir, "tank")) do
local liq = LQD(item.pos)
if liq and liq.take then
if player_name then
local num = techage.get_node_number(pos)
techage.mark_position(player_name, item.pos, "("..num..") take", "", 1)
end
taken, name = liq.take(item.pos, item.indir, name, amount)
if taken and name and taken > 0 then
break
end
end
end
return taken, name
end
function liquid.untake(pos, outdir, name, amount)
for _,item in ipairs(get_network_table(pos, outdir, "tank")) do
local liq = LQD(item.pos)
if liq and liq.untake then
amount = liq.untake(item.pos, item.indir, name, amount)
if not amount or amount == 0 then break end
end
end
return amount or 0
end
--
-- Server local functions
--
function liquid.srv_peek(pos, indir)
local nvm = techage.get_nvm(pos)
nvm.liquid = nvm.liquid or {}
return nvm.liquid.name
end
function liquid.srv_put(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
nvm.liquid = nvm.liquid or {}
amount = amount or 0
if not nvm.liquid.name then
nvm.liquid.name = name
nvm.liquid.amount = amount
return 0
elseif nvm.liquid.name == name then
nvm.liquid.amount = nvm.liquid.amount or 0
local capa = LQD(pos).capa
if nvm.liquid.amount + amount <= capa then
nvm.liquid.amount = nvm.liquid.amount + amount
return 0
else
local rest = nvm.liquid.amount + amount - capa
nvm.liquid.amount = capa
return rest
end
end
return amount
end
function liquid.srv_take(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
nvm.liquid = nvm.liquid or {}
amount = amount or 0
if not name or nvm.liquid.name == name then
name = nvm.liquid.name
nvm.liquid.amount = nvm.liquid.amount or 0
if nvm.liquid.amount > amount then
nvm.liquid.amount = nvm.liquid.amount - amount
return amount, name
else
local rest = nvm.liquid.amount
local name = nvm.liquid.name
nvm.liquid.amount = 0
nvm.liquid.name = nil
return rest, name
end
end
return 0
end
-- To be called from each node via 'tubelib2_on_update2'
-- 'output' is optional and only needed for nodes with dedicated
-- pipe sides (e.g. pumps).
function liquid.update_network(pos, outdir)
networks.node_connections(pos, Pipe)
delete_netID(pos, outdir)
end
-- To be called from each pump in 'after_dig_node'
-- before calling 'techage.del_mem(pos)'
function liquid.after_dig_pump(pos)
local nvm = techage.get_nvm(pos)
if nvm.pipe2 and nvm.pipe2.netIDs then
for outdir, netID in pairs(nvm.pipe2.netIDs) do
networks.delete_network("pipe2", netID)
end
end
end

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -17,35 +17,14 @@ local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local Pipe = techage.LiquidPipe
local networks = techage.networks
local liquid = techage.liquid
local Flip = techage.networks.Flip
local liquid = networks.liquid
local Flip = networks.Flip
local STANDBY_TICKS = 3
local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 2
local CAPA = 4
-- to mark the pump source and destinstion node
local DebugCache = {}
local function set_starter_name(pos, clicker)
local key = minetest.hash_node_position(pos)
DebugCache[key] = {starter = clicker:get_player_name(), count = 10}
end
local function get_starter_name(pos)
local key = minetest.hash_node_position(pos)
local def = DebugCache[key]
if def then
def.count = (def.count or 0) - 1
if def.count > 0 then
return def.starter
end
DebugCache[key] = nil
end
end
local State3 = techage.NodeStates:new({
node_name_passive = "techage:t3_pump",
node_name_active = "techage:t3_pump_on",
@ -63,14 +42,15 @@ local State4 = techage.NodeStates:new({
})
local function pumping(pos, nvm, state, capa)
local mem = techage.get_mem(pos)
mem.dbg_cycles = (mem.dbg_cycles or 0) - 1
local outdir = M(pos):get_int("outdir")
local starter = get_starter_name(pos)
--print("pumping", outdir, Flip[outdir])
local taken, name = liquid.take(pos, Flip[outdir], nil, capa, starter)
local taken, name = liquid.take(pos, Pipe, Flip[outdir], nil, capa, mem.dbg_cycles > 0)
if taken > 0 then
local leftover = liquid.put(pos, outdir, name, taken, starter)
if leftover then
liquid.untake(pos, Flip[outdir], name, leftover)
local leftover = liquid.put(pos, Pipe, outdir, name, taken, mem.dbg_cycles > 0)
if leftover and leftover > 0 then
liquid.untake(pos, Pipe, Flip[outdir], name, leftover)
if leftover == taken then
state:blocked(pos, nvm)
return
@ -117,25 +97,22 @@ local function on_rightclick(pos, node, clicker)
local nvm = techage.get_nvm(pos)
if node.name == "techage:t3_pump" then
set_starter_name(pos, clicker)
local mem = techage.get_mem(pos)
mem.dbg_cycles = 5
State3:start(pos, nvm)
elseif node.name == "techage:t3_pump_on" then
State3:stop(pos, nvm)
elseif node.name == "techage:t4_pump" then
set_starter_name(pos, clicker)
local mem = techage.get_mem(pos)
mem.dbg_cycles = 5
State4:start(pos, nvm)
elseif node.name == "techage:t4_pump_on" then
State4:stop(pos, nvm)
end
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
liquid.update_network(pos, outdir)
end
local function after_dig_node(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
liquid.after_dig_pump(pos)
techage.del_mem(pos)
end
@ -215,23 +192,14 @@ local ta4_tiles_act = {
},
}
local nworks = {
pipe2 = {
sides = {L = 1, R = 1}, -- Pipe connection side
ntype = "pump",
},
}
minetest.register_node("techage:t3_pump", {
description = S("TA3 Pump"),
tiles = ta3_tiles_pas,
after_place_node = after_place_node3,
on_rightclick = on_rightclick,
tubelib2_on_update2 = tubelib2_on_update2,
on_timer = node_timer3,
after_dig_node = after_dig_node,
on_rotate = screwdriver.disallow,
networks = nworks,
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
groups = {cracky=2},
@ -244,11 +212,9 @@ minetest.register_node("techage:t3_pump_on", {
tiles = ta3_tiles_act,
--after_place_node = after_place_node3,
on_rightclick = on_rightclick,
tubelib2_on_update2 = tubelib2_on_update2,
on_timer = node_timer3,
after_dig_node = after_dig_node,
on_rotate = screwdriver.disallow,
networks = nworks,
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
diggable = false,
@ -262,11 +228,9 @@ minetest.register_node("techage:t4_pump", {
tiles = ta4_tiles_pas,
after_place_node = after_place_node4,
on_rightclick = on_rightclick,
tubelib2_on_update2 = tubelib2_on_update2,
on_timer = node_timer4,
after_dig_node = after_dig_node,
on_rotate = screwdriver.disallow,
networks = nworks,
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
groups = {cracky=2},
@ -279,11 +243,9 @@ minetest.register_node("techage:t4_pump_on", {
tiles = ta4_tiles_act,
--after_place_node = after_place_node4,
on_rightclick = on_rightclick,
tubelib2_on_update2 = tubelib2_on_update2,
on_timer = node_timer4,
after_dig_node = after_dig_node,
on_rotate = screwdriver.disallow,
networks = nworks,
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
diggable = false,
@ -304,11 +266,12 @@ techage.register_node({"techage:t4_pump", "techage:t4_pump_on"}, {
end,
})
Pipe:add_secondary_node_names({
-- Pumps have to provide one output and one input side
liquid.register_nodes({
"techage:t3_pump", "techage:t3_pump_on",
"techage:t4_pump", "techage:t4_pump_on",
})
}, Pipe, "pump", {"L", "R"}, {})
minetest.register_craft({
output = "techage:t3_pump 2",
recipe = {

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -18,7 +18,7 @@ local M = minetest.get_meta
local S = techage.S
local LQD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).liquid end
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local liquid = networks.liquid
local INV_SIZE = 8
local STACKMAX = 99
@ -170,13 +170,6 @@ local tLiquid = {
end,
}
local tNetworks = {
pipe2 = {
sides = techage.networks.AllSides, -- Pipe connection sides
ntype = "tank",
},
}
minetest.register_node("techage:ta3_silo", {
description = S("TA3 Silo"),
tiles = {
@ -203,16 +196,11 @@ minetest.register_node("techage:ta3_silo", {
meta:set_string("infotext", S("TA3 Silo").." "..number)
Pipe:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
liquid.update_network(pos, outdir)
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
techage.remove_node(pos, oldnode, oldmetadata)
techage.del_mem(pos)
end,
liquid = tLiquid,
networks = tNetworks,
can_dig = can_dig,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
@ -249,16 +237,11 @@ minetest.register_node("techage:ta4_silo", {
meta:set_string("infotext", S("TA4 Silo").." "..number)
Pipe:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
liquid.update_network(pos, outdir)
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
techage.remove_node(pos, oldnode, oldmetadata)
techage.del_mem(pos)
end,
liquid = tLiquid,
networks = tNetworks,
can_dig = can_dig,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
@ -335,7 +318,7 @@ techage.register_node({"techage:ta3_silo", "techage:ta4_silo"}, {
end,
})
Pipe:add_secondary_node_names({"techage:ta3_silo", "techage:ta4_silo"})
liquid.register_nodes({"techage:ta3_silo", "techage:ta4_silo"}, Pipe, "tank", nil, tLiquid)
minetest.register_craft({
output = "techage:ta3_silo",

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -15,23 +15,25 @@
local S2P = minetest.string_to_pos
local P2S = minetest.pos_to_string
local M = minetest.get_meta
local N = tubelib2.get_node_lvm
local LQD = function(pos) return (minetest.registered_nodes[N(pos).name] or {}).liquid end
local S = techage.S
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local liquid = networks.liquid
local CAPACITY = 1000
local function on_rightclick(pos, node, clicker)
local nvm = techage.get_nvm(pos)
techage.set_activeformspec(pos, clicker)
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
minetest.get_node_timer(pos):start(2)
end
local function node_timer(pos, elapsed)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
return true
end
return false
@ -41,14 +43,19 @@ local function can_dig(pos, player)
if minetest.is_protected(pos, player:get_player_name()) then
return false
end
return liquid.is_empty(pos)
return techage.liquid.is_empty(pos)
end
local function peek_liquid(pos)
local nvm = techage.get_nvm(pos)
return liquid.srv_peek(nvm)
end
local function take_liquid(pos, indir, name, amount)
amount, name = liquid.srv_take(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
amount, name = liquid.srv_take(nvm, name, amount)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
end
return amount, name
end
@ -57,10 +64,10 @@ local function put_liquid(pos, indir, name, amount)
-- check if it is not powder
local ndef = minetest.registered_craftitems[name] or {}
if not ndef.groups or ndef.groups.powder ~= 1 then
local leftover = liquid.srv_put(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
local leftover = liquid.srv_put(nvm, name, amount, LQD(pos).capa)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
end
return leftover
end
@ -68,21 +75,14 @@ local function put_liquid(pos, indir, name, amount)
end
local function untake_liquid(pos, indir, name, amount)
local leftover = liquid.srv_put(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
local leftover = liquid.srv_put(nvm, name, amount, LQD(pos).capa)
if techage.is_activeformspec(pos) then
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", liquid.formspec(pos, nvm))
M(pos):set_string("formspec", techage.liquid.formspec(pos, nvm))
end
return leftover
end
local networks_def = {
pipe2 = {
sides = techage.networks.AllSides, -- Pipe connection sides
ntype = "tank",
},
}
minetest.register_node("techage:ta3_tank", {
description = S("TA3 Tank"),
tiles = {
@ -101,27 +101,16 @@ minetest.register_node("techage:ta3_tank", {
local number = techage.add_node(pos, "techage:ta3_tank")
meta:set_string("node_number", number)
meta:set_string("owner", placer:get_player_name())
meta:set_string("formspec", liquid.formspec(pos, nvm))
meta:set_string("formspec", techage.liquid.formspec(pos, nvm))
meta:set_string("infotext", S("TA3 Tank").." "..number)
Pipe:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
liquid.update_network(pos, outdir)
end,
on_timer = node_timer,
on_punch = liquid.on_punch,
on_punch = techage.liquid.on_punch,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
techage.remove_node(pos, oldnode, oldmetadata)
end,
liquid = {
capa = CAPACITY,
peek = liquid.srv_peek,
put = put_liquid,
take = take_liquid,
untake = untake_liquid,
},
networks = networks_def,
on_rightclick = on_rightclick,
can_dig = can_dig,
paramtype2 = "facedir",
@ -131,6 +120,16 @@ minetest.register_node("techage:ta3_tank", {
sounds = default.node_sound_metal_defaults(),
})
liquid.register_nodes({"techage:ta3_tank"},
Pipe, "tank", nil, {
capa = CAPACITY,
peek = peek_liquid,
put = put_liquid,
take = take_liquid,
untake = untake_liquid,
}
)
minetest.register_node("techage:oiltank", {
description = S("Oil Tank"),
tiles = {
@ -161,27 +160,16 @@ minetest.register_node("techage:oiltank", {
local number = techage.add_node(pos, "techage:oiltank")
meta:set_string("node_number", number)
meta:set_string("owner", placer:get_player_name())
meta:set_string("formspec", liquid.formspec(pos, nvm))
meta:set_string("formspec", techage.liquid.formspec(pos, nvm))
meta:set_string("infotext", S("Oil Tank").." "..number)
Pipe:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
liquid.update_network(pos, outdir)
end,
on_timer = node_timer,
on_punch = liquid.on_punch,
on_punch = techage.liquid.on_punch,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
techage.remove_node(pos, oldnode, oldmetadata)
end,
liquid = {
capa = CAPACITY * 4,
peek = liquid.srv_peek,
put = put_liquid,
take = take_liquid,
untake = untake_liquid,
},
networks = networks_def,
on_rightclick = on_rightclick,
can_dig = can_dig,
paramtype2 = "facedir",
@ -191,6 +179,16 @@ minetest.register_node("techage:oiltank", {
sounds = default.node_sound_metal_defaults(),
})
liquid.register_nodes({"techage:oiltank"},
Pipe, "tank", nil, {
capa = CAPACITY * 4,
peek = peek_liquid,
put = put_liquid,
take = take_liquid,
untake = untake_liquid,
}
)
minetest.register_node("techage:ta4_tank", {
description = S("TA4 Tank"),
tiles = {
@ -210,13 +208,10 @@ minetest.register_node("techage:ta4_tank", {
local number = techage.add_node(pos, "techage:ta4_tank")
meta:set_string("node_number", number)
meta:set_string("owner", placer:get_player_name())
meta:set_string("formspec", liquid.formspec(pos, nvm))
meta:set_string("formspec", techage.liquid.formspec(pos, nvm))
meta:set_string("infotext", S("TA4 Tank").." "..number)
Pipe:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
liquid.update_network(pos, outdir)
end,
on_receive_fields = function(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
@ -226,19 +221,11 @@ minetest.register_node("techage:ta4_tank", {
end
end,
on_timer = node_timer,
on_punch = liquid.on_punch,
on_punch = techage.liquid.on_punch,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
techage.remove_node(pos, oldnode, oldmetadata)
end,
liquid = {
capa = CAPACITY * 2,
peek = liquid.srv_peek,
put = put_liquid,
take = take_liquid,
untake = untake_liquid,
},
networks = networks_def,
on_rightclick = on_rightclick,
can_dig = can_dig,
paramtype2 = "facedir",
@ -248,9 +235,17 @@ minetest.register_node("techage:ta4_tank", {
sounds = default.node_sound_metal_defaults(),
})
techage.register_node({"techage:ta3_tank", "techage:ta4_tank", "techage:oiltank"}, liquid.recv_message)
liquid.register_nodes({"techage:ta4_tank"},
Pipe, "tank", nil, {
capa = CAPACITY * 2,
peek = peek_liquid,
put = put_liquid,
take = take_liquid,
untake = untake_liquid,
}
)
Pipe:add_secondary_node_names({"techage:ta3_tank", "techage:ta4_tank", "techage:oiltank"})
techage.register_node({"techage:ta3_tank", "techage:ta4_tank", "techage:oiltank"}, techage.liquid.recv_message)
minetest.register_craft({
output = "techage:ta3_tank 2",

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -17,73 +17,7 @@ local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local function switch_node(pos, node)
if node.name == "techage:ta3_valve_open" then
node.name = "techage:ta3_valve_closed"
--node.name = "default:dirt"
minetest.swap_node(pos, node)
local number = M(pos):get_string("node_number")
M(pos):set_string("infotext", S("TA3 Valve closed")..": "..number)
Pipe:after_dig_tube(pos, {name = "techage:ta3_valve_open", param2 = node.param2})
elseif node.name == "techage:ta3_valve_closed" then
node.name = "techage:ta3_valve_open"
minetest.swap_node(pos, node)
local number = M(pos):get_string("node_number")
M(pos):set_string("infotext", S("TA3 Valve open")..": "..number)
Pipe:after_place_tube(pos)
end
minetest.sound_play("techage_valve", {
pos = pos,
gain = 1,
max_hear_distance = 10})
end
local function on_rightclick(pos, node, clicker)
if not minetest.is_protected(pos, clicker:get_player_name()) then
switch_node(pos, node)
end
end
--local function node_timer(pos, elapsed)
-- if techage.is_activeformspec(pos) then
-- local nvm = techage.get_nvm(pos)
-- M(pos):set_string("formspec", liquid.formspec(pos, nvm))
-- return true
-- end
-- return false
--end
--local function can_dig(pos, player)
-- if minetest.is_protected(pos, player:get_player_name()) then
-- return false
-- end
-- return liquid.is_empty(pos)
--end
--local function take_liquid(pos, indir, name, amount)
-- amount, name = liquid.srv_take(pos, indir, name, amount)
-- if techage.is_activeformspec(pos) then
-- local nvm = techage.get_nvm(pos)
-- M(pos):set_string("formspec", liquid.formspec(pos, nvm))
-- end
-- return amount, name
--end
--local function put_liquid(pos, indir, name, amount)
-- -- check if it is not powder
-- local ndef = minetest.registered_craftitems[name] or {}
-- if not ndef.groups or ndef.groups.powder ~= 1 then
-- local leftover = liquid.srv_put(pos, indir, name, amount)
-- if techage.is_activeformspec(pos) then
-- local nvm = techage.get_nvm(pos)
-- M(pos):set_string("formspec", liquid.formspec(pos, nvm))
-- end
-- return leftover
-- end
-- return amount
--end
local liquid = networks.liquid
minetest.register_node("techage:ta3_valve_open", {
description = S("TA Valve"),
@ -102,21 +36,24 @@ minetest.register_node("techage:ta3_valve_open", {
return true
end
local meta = M(pos)
local nvm = techage.get_nvm(pos)
nvm.liquid = {}
local number = techage.add_node(pos, "techage:ta3_valve_closed")
meta:set_string("node_number", number)
meta:set_string("owner", placer:get_player_name())
meta:set_string("infotext", S("TA3 Valve open")..": "..number)
meta:set_string("infotext", S("TA3 Valve")..": "..number)
return false
end,
on_rightclick = function(pos, node, clicker)
if liquid.turn_valve_off(pos, Pipe, "techage:ta3_valve_closed", "techage:ta3_valve_open") then
minetest.sound_play("techage_valve", {
pos = pos,
gain = 1,
max_hear_distance = 10})
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_tube(pos, oldnode, oldmetadata)
end,
on_rightclick = on_rightclick,
paramtype2 = "facedir", -- important!
drawtype = "nodebox",
node_box = {
@ -146,17 +83,19 @@ minetest.register_node("techage:ta3_valve_closed", {
"techage_gaspipe_valve_hole.png",
},
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
liquid.update_network(pos, outdir)
on_rightclick = function(pos, node, clicker)
if liquid.turn_valve_on(pos, Pipe, "techage:ta3_valve_closed", "techage:ta3_valve_open") then
minetest.sound_play("techage_valve", {
pos = pos,
gain = 1,
max_hear_distance = 10})
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
techage.remove_node(pos, oldnode, oldmetadata)
end,
on_rightclick = on_rightclick,
paramtype2 = "facedir", -- important!
drawtype = "nodebox",
node_box = {
@ -180,10 +119,10 @@ techage.register_node({"techage:ta3_valve_closed", "techage:ta3_valve_open"}, {
on_recv_message = function(pos, src, topic, payload)
local node = techage.get_node_lvm(pos)
if topic == "on" and node.name == "techage:ta3_valve_closed" then
switch_node(pos, node)
liquid.turn_valve_on(pos, Pipe, "techage:ta3_valve_closed", "techage:ta3_valve_open")
return true
elseif topic == "off" and node.name == "techage:ta3_valve_open" then
switch_node(pos, node)
liquid.turn_valve_off(pos, Pipe, "techage:ta3_valve_closed", "techage:ta3_valve_open")
return true
elseif topic == "state" then
if node.name == "techage:ta3_valve_open" then
@ -196,6 +135,8 @@ techage.register_node({"techage:ta3_valve_closed", "techage:ta3_valve_open"}, {
end,
})
liquid.register_nodes({"techage:ta3_valve_closed"}, Pipe, "special", {}, {})
minetest.register_craft({
output = "techage:ta3_valve_open",
recipe = {

View File

@ -17,7 +17,7 @@ local M = minetest.get_meta
local S = techage.S
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local liquid = networks.liquid
local function is_ocean(pos)
if pos.y > 1 then
@ -33,37 +33,35 @@ local function is_ocean(pos)
M(pos):set_string("infotext", S("Error: No natural water!"))
return false
end
M(pos):set_string("infotext", S("Operational"))
return true
end
local function srv_peek(pos)
local nvm = techage.get_nvm(pos)
local function peek_liquid(pos)
local mem = techage.get_mem(pos)
if is_ocean(pos) then
nvm.liquid.name = "techage:water"
nvm.liquid.amount = 1
mem.liquid_name = "techage:water"
mem.liquid_amount = 1
else
nvm.liquid.name = nil
nvm.liquid.amount = 0
mem.liquid_name = "techage:water"
mem.liquid_amount = 0
end
return nvm.liquid.name
return mem.liquid_name
end
local function take_liquid(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
return nvm.liquid.amount, nvm.liquid.name
local mem = techage.get_mem(pos)
if not mem.liquid_name then
peek_liquid(pos)
end
return mem.liquid_amount or 0, mem.liquid_name
end
local function untake_liquid(pos, indir, name, amount)
return 0
end
local netw_def = {
pipe2 = {
sides = {U = 1}, -- Pipe connection sides
ntype = "tank",
},
}
minetest.register_node("techage:ta4_waterinlet", {
description = S("TA4 Water Inlet"),
tiles = {
@ -78,29 +76,13 @@ minetest.register_node("techage:ta4_waterinlet", {
after_place_node = function(pos, placer)
local meta = M(pos)
local nvm = techage.get_nvm(pos)
nvm.liquid = {}
Pipe:after_place_node(pos)
srv_peek(pos)
is_ocean(pos)
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
liquid.update_network(pos, outdir)
end,
--on_timer = node_timer,
--on_punch = liquid.on_punch,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
techage.remove_node(pos, oldnode, oldmetadata)
end,
liquid = {
capa = 1,
peek = liquid.srv_peek,
take = take_liquid,
untake = untake_liquid,
},
networks = netw_def,
--on_rightclick = on_rightclick,
--can_dig = can_dig,
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
groups = {cracky=2},
@ -108,7 +90,14 @@ minetest.register_node("techage:ta4_waterinlet", {
sounds = default.node_sound_metal_defaults(),
})
Pipe:add_secondary_node_names({"techage:ta4_waterinlet"})
liquid.register_nodes({"techage:ta4_waterinlet"},
Pipe, "tank", {"U"}, {
capa = 1,
peek = peek_liquid,
take = take_liquid,
untake = untake_liquid,
}
)
minetest.register_craft({
output = "techage:ta4_waterinlet",

View File

@ -17,12 +17,11 @@ local M = minetest.get_meta
local S = techage.S
local Cable = techage.ElectricCable
local power = techage.power
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local networks = techage.networks
local power = networks.power
local liquid = networks.liquid
local CYCLE_TIME = 4
local CYCLE_TIME = 2
local STANDBY_TICKS = 3
local COUNTDOWN_TICKS = 3
local PWR_NEEDED = 4
@ -51,12 +50,11 @@ local function can_start(pos, nvm, state)
end
local function start_node(pos, nvm, state)
power.consumer_start(pos, Cable, CYCLE_TIME)
nvm.running = true
end
local function stop_node(pos, nvm, state)
nvm.running = false
power.consumer_stop(pos, Cable)
end
local State = techage.NodeStates:new({
@ -70,30 +68,31 @@ local State = techage.NodeStates:new({
stop_node = stop_node,
})
local function on_power(pos)
local nvm = techage.get_nvm(pos)
State:start(pos, nvm)
nvm.running = true
end
local function on_nopower(pos)
local nvm = techage.get_nvm(pos)
State:nopower(pos, nvm)
nvm.running = false
local function has_power(pos, nvm)
local outdir = networks.Flip[M(pos):get_int("waterdir")]
local taken = power.consume_power(pos, Cable, outdir, PWR_NEEDED)
if techage.is_running(nvm) then
if taken < PWR_NEEDED then
State:nopower(pos, nvm)
else
return true -- keep running
end
elseif taken == PWR_NEEDED then
State:start(pos, nvm)
end
end
local function pumping(pos, nvm)
if techage.needs_power(nvm) then
power.consumer_alive(pos, Cable, CYCLE_TIME)
end
if nvm.running then
local leftover = liquid.put(pos, 6, "techage:water", 1)
if leftover and leftover > 0 then
State:blocked(pos, nvm)
return
if has_power(pos, nvm) then
nvm.ticks = (nvm.ticks or 0) + 1
if nvm.ticks % 4 == 0 then
local leftover = liquid.put(pos, Pipe, 6, "techage:water", 1)
if leftover and leftover > 0 then
State:blocked(pos, nvm)
return
end
end
State:keep_running(pos, nvm, COUNTDOWN_TICKS)
return
State:keep_running(pos, nvm, 1)
end
end
@ -126,32 +125,9 @@ end
local function after_dig_node(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
Cable:after_dig_node(pos)
liquid.after_dig_pump(pos)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
if tlib2.tube_type == "pipe2" then
liquid.update_network(pos, outdir, tlib2)
else
power.update_network(pos, outdir, tlib2)
end
end
local netw_def = {
pipe2 = {
sides = {U = 1}, -- Pipe connection sides
ntype = "pump",
},
ele1 = {
sides = {L = 1}, -- Cable connection sides
ntype = "con1",
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED,
},
}
minetest.register_node("techage:t4_waterpump", {
description = S("TA4 Water Pump"),
tiles = {
@ -166,8 +142,6 @@ minetest.register_node("techage:t4_waterpump", {
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = netw_def,
on_receive_fields = on_receive_fields,
on_timer = node_timer,
@ -177,21 +151,11 @@ minetest.register_node("techage:t4_waterpump", {
is_ground_content = false,
})
Cable:add_secondary_node_names({"techage:t4_waterpump"})
Pipe:add_secondary_node_names({"techage:t4_waterpump"})
power.register_nodes({"techage:t4_waterpump"}, Cable, "con", {"L"})
liquid.register_nodes({"techage:t4_waterpump"}, Pipe, "pump", {"U"}, {})
techage.register_node({"techage:t4_waterpump"}, {
on_recv_message = function(pos, src, topic, payload)
return State:on_receive_message(pos, topic, payload)
end,
})
--minetest.register_craft({
-- output = "techage:t4_waterpump",
-- recipe = {
-- {"", "default:mese_crystal", ""},
-- {"", "techage:ta3_liquidsampler_pas", ""},
-- {"", "techage:ta4_wlanchip", ""},
-- },
--})

View File

@ -7,20 +7,6 @@
TA3 Accu Box=Akkublock
TA3 Akku Box=TA3 Akku Block
### akkubox.lua ###
### battery.lua ###
Load=Ladung
### akkubox.lua ###
### electrolyzer.lua ###
### fuelcell.lua ###
### generator.lua ###
### heatexchanger2.lua ###
### tiny_generator.lua ###
Electricity=Strom
### aluminium.lua ###
Aluminum=Aluminium
@ -42,7 +28,6 @@ Autocrafter=Autocrafter
### axle2power.lua ###
TA2 Power Generator=TA2 Stromgenerator
TA2 Power Generator: Overload fault?@n(restart with right-click)=TA2 Stromgenerator: Überlastfehler?@n(Neustart mit Rechtsklick)
### baborium.lua ###
@ -82,6 +67,11 @@ Battery=Batterie
Coal Equivalents=Kohleeinheiten
Digtron Battery=Digtron Akku
### battery.lua ###
### storage.lua ###
Load=Ladung
### bauxit.lua ###
Bauxite Cobblestone=Bauxit Kopfsteinpflaster
@ -139,6 +129,7 @@ Insert destination node number(s)=Gebe Zielnummer(n) ein
### doorcontroller.lua ###
### mesecons_converter.lua ###
### repeater.lua ###
### submenu.lua ###
Save=Speichern
@ -286,15 +277,35 @@ TA2 Drive Axle=TA2 Antriebsachse
TA Electric Cable=TA Stromkabel
### electrolyzer.lua ###
### electricmeter.lua ###
TA4 Electrolyzer=TA4 Elektrolyseur
full=voll
Consumption=Verbrauch
TA4 Electric Meter=TA4 Stromzähler
### electricmeter.lua ###
### formspecs.lua ###
### transformer.lua ###
Power=Strom
### electrolyzer.lua ###
### power_terminal2.lua ###
Configurable value@nfor the current limit=Konfigurierbarer Wert@nfür die Strombegrenzung
Current limitation=Strombegrenzung
Electrolyzer=Eletrolyseur
If the charge of the storage@nsystem exceeds the configured value,@nthe block switches off=Überschreitet die Ladung des@nSpeichersystems den konfigurierten@nWert, schaltet sich der Block ab
Maximum possible@ncurrent consumption=Maximal mögliche Stromaufnahme
Maximum power consumption [ku]=maximale Stromaufnahme
Storage full=Speicher voll
TA4 Electrolyzer=TA4 Elektrolyseur
Turnoff point=Abschaltpunkt
Turnoff point reached=Abschaltpunkt erreicht
### electrolyzer.lua ###
### fuelcell.lua ###
### tiny_generator.lua ###
Electricity=Strom
### electronic.lua ###
@ -345,13 +356,6 @@ Firebox=Feuerkasten
Flywheel=Schwungrad
TA2 Flywheel=TA2 Schwungrad
### flywheel.lua ###
### generator.lua ###
### solarcell.lua ###
### source.lua ###
power=Energie
### forceload.lua ###
Area already loaded or max. number of Forceload Blocks reached!=Bereich bereits geladen oder maximale Anzahl von Forceload Blöcken erreicht!
@ -363,6 +367,27 @@ Techage Forceload Block=Techage Forceload Block
Techage Forceload Tile=Techage Forceload Kachel
loaded=geladen
### formspecs.lua ###
Charge termination=Ladebegrenzung
Current output [ku]=Aktueller Ausgabewert
Maximum output [ku]=Maximaler Ausgabewert
Range in which the generator reduces its power=Bereich in dem der Generator die Leistung reduziert
The current power the generator provides=Die aktuelle Leistung die der Generator liefert
The maximum power the generator can provide=Die maximale Leistung die der Generator liefern kann
### formspecs.lua ###
### power_terminal2.lua ###
Charging=Laden
### formspecs.lua ###
### power_terminal2.lua ###
### storage.lua ###
### transformer.lua ###
Storage=Speicher
### fuel_lib.lua ###
Fuel Menu=Brennstoff Menü
@ -370,13 +395,9 @@ To add fuel punch@nthis block@nwith a fuel container=Um Brennstoff nachzufüllen
### fuelcell.lua ###
Cat. 1 generator=Kat. 1 Generator
Cat. 2 generator=Kat. 2 Generator
Fuel Cell=Brennstoffzelle
If set, fuelcell will work@nas cat. 1 generator=Wenn gesetzt, Brennstoffzelle@narbeitet als Kat. 1 Generator
TA4 Fuel Cell=TA4 Brennstoffzelle
TA4 Fuel Cell Gen1=TA4 Brennstoffzelle Gen1
TA4 Fuel Cell Gen2=TA4 Brennstoffzelle Gen2
no hydrogen=kein Wasserstoff
### fuelcellstack.lua ###
@ -398,10 +419,13 @@ TA2 Gearbox=TA2 Getriebeblock
### generator.lua ###
Generator=Generator
TA3 Generator=TA3 Generator
TA4 Generator=TA4 Generator
storage empty?=Speicher leer?
### generator.lua ###
### power_terminal2.lua ###
Generator=Generator
### gravelrinser.lua ###
@ -450,20 +474,15 @@ TA4 Furnace Heater=TA4 Ofenheizung
### heatexchanger1.lua ###
TA4 Heat Exchanger 1=TA4 Wärmetauscher 1
inlet/pipe error=Einlass/Röhrenfehler
wrong storage diameter=Falscher Wärmespeicher-Durchmesser
### heatexchanger1.lua ###
### heatexchanger2.lua ###
did you check the plan?=hast du den Plan geprüft?
### heatexchanger2.lua ###
Heat Exchanger=Wärmetauscher
Power network connection error=Stromnetz Verbindungsfehler
TA4 Heat Exchanger=TA4 Wärmetauscher
TA4 Heat Exchanger 2=TA4 Wärmetauscher 2
Thermal=Wärme
did you check the plan?=hast du den Plan geprüft?
inlet/pipe error=Einlass/Röhrenfehler
wrong storage diameter=Falscher Wärmespeicher-Durchmesser
### heatexchanger3.lua ###
@ -494,6 +513,10 @@ TA4 LED Industrial Lamp=TA4 LED Industrielampe
### inlet.lua ###
TA4 Pipe Inlet=TA4 Rohrzulauf
one window maximum=maximal ein Fenster
wrong diameter (should be 5, 7, or 9)=falscher Durchmesser (sollte 5, 7, oder 9 sein)
wrong number of gravel nodes=falsche Anzahl von Kiesblöcken
wrong number of shell nodes=falsche Anzahl von Blöcken bei der Hülle
### inverter.lua ###
@ -501,6 +524,8 @@ Inverter=Wechselrichter
Power AC=Wechselstrom
Power DC=Gleichstrom
TA4 Solar Inverter=TA4 Solar Wechselrichter
no solar power=keine Solarleistung
solar network error=Solar-Netzwerk Fehler
### junctionbox.lua ###
@ -523,6 +548,10 @@ TA4 Laser Beam Receiver=TA4 Laserstrahl Empfänger
Valid destination positions:=Gültige Zielpositionen
to=bis
### lib.lua ###
Block has an@nadditional wrench menu=Block besitzt ein@nzusätzliches@nSchraubenschlüssel-Menü
### lib.lua ###
### sensorchest.lua ###
@ -574,15 +603,10 @@ Syntax=Syntax
### logic_block.lua ###
### lua_logic.lua ###
Store=Speichern
TA3 Logic Block=TA3 Logikblock
Update=Update
### logic_block.lua ###
### lua_logic.lua ###
### power_terminal2.lua ###
Store=Speichern
### lye.lua ###
Lye=Lauge
@ -695,7 +719,6 @@ Silver Sandstone Powder=Silbersandstein Pulver
### power2axle.lua ###
TA3 Electric Motor=TA3 Elektromotor
TA3 Electric Motor: Overload fault?@n(restart with right-click)=TA3 Elektromotor: Überlastfehler?@n(Neustart mit Rechtsklick)
### power_line.lua ###
@ -704,57 +727,16 @@ TA Power Pole=TA Strommast
TA Power Pole Top (for up to 6 connections)=TA Strommastkopf (für bis zu 6 Verbindungen)
TA Power Pole Top 2 (for landlines)=TA Strommastkopf 2 (für Überlandleitungen)
### power_terminal.lua ###
Active:=Aktiv:
All nodes:=Alle Blöcke:
Consum. 1=Konsum. 1
Consum. 2=Konsum. 2
Genera. 1=Genera. 1
Genera. 2=Genera. 2
In use:=In Benutzung:
No network or active generator available!=Kein Stromnetz oder aktiver Generator verfügbar
Number of all nodes=Anzahl aller Blöcke
TA3 Power Terminal Old=TA3 Strom Terminal Alt
The network is overloaded!=Das Stromnetz ist überlastet!
The network load is almost at the limit!=Das Stromnetz ist ziemlich am Limit!
Turned on:=Eingeschaltet:
With %u of a maximum of %u blocks you are almost at the limit!=Mit %u von maximal %u Blöcken bist du fast am Limit!
### power_terminal.lua ###
### power_terminal2.lua ###
Commands@nhelp . . . print this text@ncls . . . . . clear screen@ngen . . . . print all generators@nsto . . . . . print all storage systems@n=Kommandos@nhelp . . . diesen Text ausgeben@ncls . . . . . Bildschirm löschen@ngen . . . . Alle Generatoren ausgeben@nsto . . . . . Alle Speichersysteme ausgeben@n
Consumer=Verbraucher
Network Data=Netzwerkdaten
### power_terminal2.lua ###
Accu Box=Akkublock
Current power:=Strom aktuell:
Energy storage=Engergiespeicher
Energy stored:=Energie gespeichert
Fuel cell cat. 1=Brennstoffzelle Kat. 1
Fuel cell cat. 2=Brennstoffzelle Kat. 2
Generators=Generatoren
Intake=Stromaufnahme
Max. needed power=Max. benötigter Strom
Maximum power:=Maximalstrom:
No power grid or running generator!=Kein Stromnetz oder Generator verfügbar!
Number blocks:=Anzahl Blöcke:
Number of power grid blocks=Anzahl der Stromnetz Blöcke
Output=Stromabgabe
Power grid total=Stromnetz gesammt
Power station=Kraftwerk
Probably too many consumers (=Vermutlich zu viele Verbraucher (
Select type=Wähle Typ
Solar system=Solaranlage
Storage systems=Speichersysteme
TA2 Generator=TA2 Generator
Number of consumers:=Anzahl der Verbraucher
Number of generators:=Anzahl der Generatoren
Number of network nodes:=Anzahl von Netzwerkblöcken
Number of storage systems:=Anzahl der Speichersysteme
TA3 Power Terminal=TA3 Strom Terminal
Tiny generator=Kleingenerator
To many blocks in the power grid!=Zu viele Blöcke im Stromnetz!
Type=Typ
Wind turbine=Windkraftanlage
ku is needed=ku wird benötigt
### power_terminal2.lua ###
### terminal.lua ###
@ -767,6 +749,7 @@ TA Power Switch=TA Stromschalter
TA Power Switch Small=TA Stromschalter klein
### powerswitchbox.lua ###
### powerswitchbox_legacy.lua ###
TA Power Switch Box=TA Stromschalterbox
@ -817,7 +800,6 @@ inventory full=Inventar ist voll
### reboiler.lua ###
TA3 Oil Reboiler=TA3 Aufkocher
TA3 Oil Reboiler: blocked=TA3 Aufkocher: blockiert
### recipe_lib.lua ###
@ -852,7 +834,6 @@ Position=Position
Position temperature=Positionstemperatur
TechAge Info Tool (use @= read status info)=TechAge Info Werkzeug
TechAge Repair Kit=TechAge Reparaturset
repaired=repariert
### repeater.lua ###
@ -904,12 +885,17 @@ TA4 Solar Carrier Module T=TA4 Solar Trägermodul O
TA4 Solar Module=TA4 Solarmodul
light=Licht
### solarcell.lua ###
### source.lua ###
power=Strom
### source.lua ###
Axle Power Source=Achsenkraftquelle
Ele Power Source=Ele Kraftquelle
Power Source=Stromquelle
Steam Power Source=Dampfenergiequelle
Test Generator=Test Generator
### steam_pipe.lua ###
@ -919,6 +905,10 @@ TA2 Steam Pipe=TA2 Dampfleitung
TechAge Steel Mat=TechAge Stahlmatte
### storage.lua ###
Test Storage=Test Speicher
### streetlamp.lua ###
TA Street Lamp=TA Straßenlampe
@ -929,6 +919,20 @@ TA4 LED Street Lamp=TA4 LED Straßenlampe
TA4 LED Street Lamp Arm=TA4 LED Lampenarm
TA4 LED Street Lamp Pole=TA4 LED Lampenmast
### submenu.lua ###
Cancel=Abbruch
Note: You can't change any values while the block is running!=Hinweis: Während der Block läuft, kann kein Wert geändert werden!
Refresh=Aktualisieren
### ta2_weight_chest.lua ###
TA2 Weight Chest=TA2 Gewichtekiste
### ta2_winch.lua ###
TA2 Winch=TA2 Seilwinde
### ta4_cable.lua ###
TA4 Low Power Box=TA4 Niederspannungsverteilerbox
@ -1028,10 +1032,13 @@ TA4 Derrick=TA4 Bohrturm
[TA] Derrick is being built!=[TA] Bohrturm wird errichtet
[TA] Derrick is being removed!=[TA] Bohrturm wird abgebaut
### transformer.lua ###
TA4 Isolation Transformer=TA4 Trenntransformator
### trowel.lua ###
TechAge Trowel=TechAge Kelle
Use a trowel to remove the node.=Verwende eine Kelle, um den Block zu entfernen.
### tube_wall_entry.lua ###
@ -1058,8 +1065,7 @@ Usmium Powder=Usmium Pulver
### valve.lua ###
TA Valve=TA Ventil
TA3 Valve closed=TA3 Ventil zu
TA3 Valve open=TA3 Ventil offen
TA3 Valve=TA3 Ventil
### waterinlet.lua ###
@ -1085,8 +1091,3 @@ This is not the surface of the ocean!=Das ist nicht die Meeresoberfläche!
biome and no ocean!=Biom und keine Meer (ocean)!
is a suitable place for a wind turbine!=ist ein geeigneter Ort für eine Windkraftanlage!
##### not used anymore #####
Fuel cell=Brennstoffzelle
Not suitable position!=Ungeeignete Position!

View File

@ -7,20 +7,6 @@
TA3 Accu Box=
TA3 Akku Box=
### akkubox.lua ###
### battery.lua ###
Load=
### akkubox.lua ###
### electrolyzer.lua ###
### fuelcell.lua ###
### generator.lua ###
### heatexchanger2.lua ###
### tiny_generator.lua ###
Electricity=
### aluminium.lua ###
Aluminum=
@ -42,7 +28,6 @@ Autocrafter=
### axle2power.lua ###
TA2 Power Generator=
TA2 Power Generator: Overload fault?@n(restart with right-click)=
### baborium.lua ###
@ -82,6 +67,11 @@ Battery=
Coal Equivalents=
Digtron Battery=
### battery.lua ###
### storage.lua ###
Load=
### bauxit.lua ###
Bauxite Cobblestone=
@ -139,6 +129,7 @@ Insert destination node number(s)=
### doorcontroller.lua ###
### mesecons_converter.lua ###
### repeater.lua ###
### submenu.lua ###
Save=
@ -286,15 +277,35 @@ TA2 Drive Axle=
TA Electric Cable=
### electrolyzer.lua ###
### electricmeter.lua ###
TA4 Electrolyzer=
full=
Consumption=
TA4 Electric Meter=
### electricmeter.lua ###
### formspecs.lua ###
### transformer.lua ###
Power=
### electrolyzer.lua ###
### power_terminal2.lua ###
Configurable value@nfor the current limit=
Current limitation=
Electrolyzer=
If the charge of the storage@nsystem exceeds the configured value,@nthe block switches off=
Maximum possible@ncurrent consumption=
Maximum power consumption [ku]=
Storage full=
TA4 Electrolyzer=
Turnoff point=
Turnoff point reached=
### electrolyzer.lua ###
### fuelcell.lua ###
### tiny_generator.lua ###
Electricity=
### electronic.lua ###
@ -345,13 +356,6 @@ Firebox=
Flywheel=
TA2 Flywheel=
### flywheel.lua ###
### generator.lua ###
### solarcell.lua ###
### source.lua ###
power=
### forceload.lua ###
Area already loaded or max. number of Forceload Blocks reached!=
@ -363,6 +367,27 @@ Techage Forceload Block=
Techage Forceload Tile=
loaded=
### formspecs.lua ###
Charge termination=
Current output [ku]=
Maximum output [ku]=
Range in which the generator reduces its power=
The current power the generator provides=
The maximum power the generator can provide=
### formspecs.lua ###
### power_terminal2.lua ###
Charging=
### formspecs.lua ###
### power_terminal2.lua ###
### storage.lua ###
### transformer.lua ###
Storage=
### fuel_lib.lua ###
Fuel Menu=
@ -370,13 +395,9 @@ To add fuel punch@nthis block@nwith a fuel container=
### fuelcell.lua ###
Cat. 1 generator=
Cat. 2 generator=
Fuel Cell=
If set, fuelcell will work@nas cat. 1 generator=
TA4 Fuel Cell=
TA4 Fuel Cell Gen1=
TA4 Fuel Cell Gen2=
no hydrogen=
### fuelcellstack.lua ###
@ -398,10 +419,13 @@ TA2 Gearbox=
### generator.lua ###
Generator=
TA3 Generator=
TA4 Generator=
storage empty?=
### generator.lua ###
### power_terminal2.lua ###
Generator=
### gravelrinser.lua ###
@ -450,20 +474,15 @@ TA4 Furnace Heater=
### heatexchanger1.lua ###
TA4 Heat Exchanger 1=
inlet/pipe error=
wrong storage diameter=
### heatexchanger1.lua ###
### heatexchanger2.lua ###
did you check the plan?=
### heatexchanger2.lua ###
Heat Exchanger=
Power network connection error=
TA4 Heat Exchanger=
TA4 Heat Exchanger 2=
Thermal=
did you check the plan?=
inlet/pipe error=
wrong storage diameter=
### heatexchanger3.lua ###
@ -494,6 +513,10 @@ TA4 LED Industrial Lamp=
### inlet.lua ###
TA4 Pipe Inlet=
one window maximum=
wrong diameter (should be 5, 7, or 9)=
wrong number of gravel nodes=
wrong number of shell nodes=
### inverter.lua ###
@ -501,6 +524,8 @@ Inverter=
Power AC=
Power DC=
TA4 Solar Inverter=
no solar power=
solar network error=
### junctionbox.lua ###
@ -523,6 +548,10 @@ TA4 Laser Beam Receiver=
Valid destination positions:=
to=
### lib.lua ###
Block has an@nadditional wrench menu=
### lib.lua ###
### sensorchest.lua ###
@ -574,15 +603,10 @@ Syntax=
### logic_block.lua ###
### lua_logic.lua ###
Store=
TA3 Logic Block=
Update=
### logic_block.lua ###
### lua_logic.lua ###
### power_terminal2.lua ###
Store=
### lye.lua ###
Lye=
@ -695,7 +719,6 @@ Silver Sandstone Powder=
### power2axle.lua ###
TA3 Electric Motor=
TA3 Electric Motor: Overload fault?@n(restart with right-click)=
### power_line.lua ###
@ -704,57 +727,16 @@ TA Power Pole=
TA Power Pole Top (for up to 6 connections)=
TA Power Pole Top 2 (for landlines)=
### power_terminal.lua ###
Active:=
All nodes:=
Consum. 1=
Consum. 2=
Genera. 1=
Genera. 2=
In use:=
No network or active generator available!=
Number of all nodes=
TA3 Power Terminal Old=
The network is overloaded!=
The network load is almost at the limit!=
Turned on:=
With %u of a maximum of %u blocks you are almost at the limit!=
### power_terminal.lua ###
### power_terminal2.lua ###
Commands@nhelp . . . print this text@ncls . . . . . clear screen@ngen . . . . print all generators@nsto . . . . . print all storage systems@n=
Consumer=
Network Data=
### power_terminal2.lua ###
Accu Box=
Current power:=
Energy storage=
Energy stored:=
Fuel cell cat. 1=
Fuel cell cat. 2=
Generators=
Intake=
Max. needed power=
Maximum power:=
No power grid or running generator!=
Number blocks:=
Number of power grid blocks=
Output=
Power grid total=
Power station=
Probably too many consumers (=
Select type=
Solar system=
Storage systems=
TA2 Generator=
Number of consumers:=
Number of generators:=
Number of network nodes:=
Number of storage systems:=
TA3 Power Terminal=
Tiny generator=
To many blocks in the power grid!=
Type=
Wind turbine=
ku is needed=
### power_terminal2.lua ###
### terminal.lua ###
@ -767,6 +749,7 @@ TA Power Switch=
TA Power Switch Small=
### powerswitchbox.lua ###
### powerswitchbox_legacy.lua ###
TA Power Switch Box=
@ -817,7 +800,6 @@ inventory full=
### reboiler.lua ###
TA3 Oil Reboiler=
TA3 Oil Reboiler: blocked=
### recipe_lib.lua ###
@ -852,7 +834,6 @@ Position=
Position temperature=
TechAge Info Tool (use @= read status info)=
TechAge Repair Kit=
repaired=
### repeater.lua ###
@ -904,12 +885,17 @@ TA4 Solar Carrier Module T=
TA4 Solar Module=
light=
### solarcell.lua ###
### source.lua ###
power=
### source.lua ###
Axle Power Source=
Ele Power Source=
Power Source=
Steam Power Source=
Test Generator=
### steam_pipe.lua ###
@ -919,6 +905,10 @@ TA2 Steam Pipe=
TechAge Steel Mat=
### storage.lua ###
Test Storage=
### streetlamp.lua ###
TA Street Lamp=
@ -929,6 +919,20 @@ TA4 LED Street Lamp=
TA4 LED Street Lamp Arm=
TA4 LED Street Lamp Pole=
### submenu.lua ###
Cancel=
Note: You can't change any values while the block is running!=
Refresh=
### ta2_weight_chest.lua ###
TA2 Weight Chest=
### ta2_winch.lua ###
TA2 Winch=
### ta4_cable.lua ###
TA4 Low Power Box=
@ -1028,10 +1032,13 @@ TA4 Derrick=
[TA] Derrick is being built!=
[TA] Derrick is being removed!=
### transformer.lua ###
TA4 Isolation Transformer=
### trowel.lua ###
TechAge Trowel=
Use a trowel to remove the node.=
### tube_wall_entry.lua ###
@ -1058,8 +1065,7 @@ Usmium Powder=
### valve.lua ###
TA Valve=
TA3 Valve closed=
TA3 Valve open=
TA3 Valve=
### waterinlet.lua ###

View File

@ -106,33 +106,3 @@ minetest.register_craft({
{"group:wood", "", ""},
},
})
minetest.register_lbm({
label = "Upgrade doors and gates",
name = "techage:replace_legacy_doors_and_gates",
nodenames = {
"techage:doorblock19",
"techage:doorblock20",
"techage:gateblock19",
"techage:gateblock20",
},
run_at_every_load = false,
action = function(pos, node)
if node.name == "techage:doorblock19" then
node.name = "techage:doorblock21"
elseif node.name == "techage:doorblock20" then
node.name = "techage:doorblock22"
elseif node.name == "techage:gateblock19" then
node.name = "techage:gateblock21"
elseif node.name == "techage:gateblock20" then
node.name = "techage:gateblock22"
end
minetest.swap_node(pos, node)
end,
})

View File

@ -74,7 +74,7 @@ Since the levels build on each other, all ages have to be run through one after
## Power Consumption
| TechAge Machine | TA2 [ku] | TA3 [ku] | TA4 [ku] |
t| TechAge Machine | TA2 [ku] | TA3 [ku] | TA4 [ku] |
| ------------------------------ | -------- | -------- | --------- |
| Autocrafter | 4 | 6 | (9) |
| Electronic Fab | 8 | 12 | 12 |
@ -93,9 +93,7 @@ Since the levels build on each other, all ages have to be run through one after
| TA4 Reactor | - | - | 8 |
| Steam Engine | 25 | | |
| Coal Power Station | | 80 | |
| TA3 Accu Box | | 10 | |
| TA3 Tiny Power Generator | | 12 | |
| TA4 Energy Storage Generator | | | 60 |
| TA4 Solar Inverter | | | up to 100 |
| TA4 Wind Turbine | | | 70 |

View File

@ -37,6 +37,29 @@ Ab TA3 laufen die Maschinen mit Strom und besitzen eine Kommunikationsschnittste
Mit TA4 kommen weitere Stromquellen dazu, aber auch höhere logistische Herausforderungen (Stromtrassen, Item Transport).
## Änderungen ab Version 1.0
Ab V1.0 (17.07.2021) hat sich folgendes geändert:
- Der Algorithmus zur Berechnung der Stromverteilung hat sich geändert. Energiespeichersystem werden dadurch wichtiger. Diese gleichen Schankungen aus, was bei größeren Netzen mit mehreren Generatoren wichtig wird.
- Aus diesem Grund hat TA2 seinen eigenen Energiespeicher erhalten.
- Die Akkublöcke aus TA3 dienen auch als Energiespeicher. Ihre Funktionsweise wurde entsprechend angepasst.
- Das TA4 Speichersystem wurde überarbeitet. Die Wärmetauscher (heatexchanger) haben eine neue Nummer bekommen, da die Funktionalität vom unteren in den mittleren Block verschoben wurde. Sofern diese ferngesteuert wurden, muss die Knotennummer angepasst werden. Die Generatoren haben kein eigenes Menü mehr, sondern werden nur noch über den Wärmetauscher ein-/ausgeschaltet. Wärmetauscher und Generator müssen jetzt am gleichen Netz hängen!
- Mehrere Stromnetze können jetzt über einen TA4 Transformator Blöcke gekoppelt werden.
- Neu ist auch ein TA4 Stromzähler Block für Unternetze.
### Tipps zur Umstellung
Viele weitere Blöcke haben kleinere Änderungen bekommen. Daher kann es sein, dass Maschinen oder Anlagen nach der Umstellung nicht gleich wieder anlaufen. Sollte es zu Störungen kommen, helfen folgende Tipps:
- Maschinen aus- und wieder eingeschalten
- ein Stromkabel-Block entfernen und wieder setzen
- den Block ganz entfernen und wieder setzen
- mindestens ein Akkublock oder Speichersystem in jedes Netzwerk
## Erze und Mineralien
Techage fügt dem Spiel einige neue Items hinzu:
@ -48,6 +71,7 @@ Techage fügt dem Spiel einige neue Items hinzu:
- Bauxit - ein Aluminiumerz, was in TA4 zur Herstellung von Aluminium benötigt wird
- Basalt - entsteht, wenn sich Wasser und Lave berühren
### Meridium
Meridium ist eine Legierung aus Stahl und Mesekristallen. Meridium Ingots können mit dem Kohlebrenner aus Stahl und Mesesplitter hergestellt werden. Meridium leuchtet im Dunkeln. Auch Werkzeuge aus Meridium leuchten und sind daher im Untertagebau sehr hilfreich.
@ -87,22 +111,10 @@ Es wird zur Herstellung von Aluminium benötigt, was vor allem in TA4 Verwendung
### Basalt
Basalt entsteht nur, wenn Lava und Wasser zusammenkommen.
Basalt entsteht nur, wenn Lava und Wasser zusammen kommen.
Dazu sollte man am besten eine Anlage aufbauen, bei der eine Lava- und eine Wasserquelle zusammenfließen.
Dort wo sich beide Flüssigkeiten treffen, entsteht Basalt.
Einen automatisierten Basalt Generator kann man mit dem Sign Bot aufbauen.
[basalt|image]
## History
- 28.09.2019: Um Solaranlage erweitert
- 05.10.2019: Daten zur Solaranlage und Beschreibung zum Wechselrichter und zum Power-Terminal geändert
- 18.11.2019: Kapitel für Erze, Reaktor, Aluminium, Silo, Bauxit, Ofenheizung, Kieswaschanlage hinzugefügt
- 22.02.2020: Korrekturen und Kapitel zum Update
- 29.02.2020: ICTA Controller hinzugefügt und weitere Korrekturen
- 14.03.2020 Lua Controller hinzugefügt und weitere Korrekturen
- 22.03.2020 Weitere TA4 Blöcke hinzugefügt

View File

@ -37,6 +37,30 @@ From TA3, the machines run on electricity and have a communication interface for
TA4 adds more power sources, but also higher logistical challenges (power lines, item transport).
## Changes from version 1.0
From V1.0 (07/17/2021) the following has changed:
- The algorithm for calculating the power distribution has changed. This makes energy storage systems more important. These compensate for fluctuations, which is important in larger networks with several generators.
- For this reason TA2 got its own energy storage.
- The battery blocks from TA3 also serve as energy storage. Their functionality has been adapted accordingly.
- The TA4 storage system has been revised. The heat heat exchanger have been given a new number because the functionality has been moved from the lower to the middle block. If these were remotely controlled, the node number must be adapted. The generators no longer have their own menu, but are only switched on / off via the heat exchanger. The heat exchanger and generator must now be connected to the same network!
- Several power grids can now be coupled via a TA4 transformer blocks.
- A TA4 electricity meter block for sub-networks is also new.
- At least one battery block or a storage system in each network
### Tips on switching
Many more blocks have received minor changes. It is therefore possible that machines or systems do not start up again immediately after the changeover. In the event of malfunctions, the following tips will help:
- Switch machines off and on again
- remove a power cable block and put it back in place
- remove the block completely and put it back in place
## Ores and Minerals
Techage adds some new items to the game:

View File

@ -23,7 +23,7 @@ Der Boiler muss mit Wasser gefüllt werden. Dazu bis zu 10 Eimer Wasser in den B
Die Feuerbox muss mit Kohle oder Holzkohle gefüllt werden.
Wenn das Wasser heiß ist (Temperaturanzeige ganz oben), kann die Dampfmaschine am Schwungrad gestartet werden.
Die Dampfmaschine leistet 25 ku, kann damit mehrere Maschinen gleichzeitig antreiben.
Die Dampfmaschine leistet 25 ku und kann damit mehrere Maschinen gleichzeitig antreiben.
[steamengine|plan]
@ -66,7 +66,7 @@ Teil der Dampfmaschine. Der Boiler muss mit dem Zylinder über die Dampfleitunge
### TA2 Antriebsachsen / TA2 Drive Axle
Die Antriebsachsen dienen zur Kraftübertragung von der Dampfmaschine zu anderen Maschinen. Die maximale Länge einer Antriebsachse beträgt 8 Blöcke. Über Getriebeboxen können auch größere Strecken überbrückt, sowie Abzweigungen und Richtungswechsel realisiert werden.
Die Antriebsachsen dienen zur Kraftübertragung von der Dampfmaschine zu anderen Maschinen. Die maximale Länge einer Antriebsachse beträgt 10 Blöcke. Über Getriebeboxen können auch größere Strecken überbrückt, sowie Abzweigungen und Richtungswechsel realisiert werden.
[ta2_driveaxle|image]
@ -81,6 +81,33 @@ Das Stromgenerator nimmt primär max. 25 ku an Achsenkraft auf und gibt sekundä
[ta2_generator|image]
## TA2 Energiespeicher
Bei größeren Anlagen mit mehreren Dampfmaschinen oder vielen angetriebenen Maschinen empfiehlt sich ein Energiespeicher. Der Energiespeicher bei TA2 arbeitet mit Lageenergie. Dazu wird Balast (Steine, Kies) in einer Kiste mit Hilfe einer Seilwinde in die Höhe gezogen. Ist überschüssige Energie im Achsen-Netzwerk vorhanden, so wird die Kiste nach oben gezogen. Wird kurzfristig mehr Energie benötigt, als die Dampfmaschine liefern kann, so gibt der Energiespeicher die gespeicherte Energie wieder ab, und die Balast-Kiste bewegt sich wieder nach unten.
Der Energiespeicher besteht aus mehreren Blöcken und muss wie im Plan rechts abgebildet, zusammen gebaut werden.
Um die maximale Speicherkapazität zu erreichen, muss die Kiste mit Gewichten komplett gefüllt, und der Mast inklusive der zwei Getriebeboxen 12 Blöcke hoch sein. Kleinere Aufbauten sind aber auch möglich.
[ta2_storage|plan]
### TA2 Seilwinde / TA2 Winch
Die Seilwinde muss mit einer Getriebebox verbunden werden und kann so überschüssige Energie aufnehmen und damit eine Gewichtekiste nach oben ziehen. Die maximale Seillänge beträgt 10 Blöcke.
[ta2_winch|image]
### TA2 Gewichtekiste / TA2 Weight Chest
Diese Kiste muss mit bis zu 10 Blöcken Abstand unter die Seilwinde gesetzt und mit Pflastersteinen Kies oder Sand gefüllt werden. Ist das Mindestgewicht von einem Stack (99+ Items) erreicht und überschüssige Energie vorhanden, wird die Kiste automatisch über eine Seil mit der Seilwinde verbunden und in die Höhe gezogen.
[ta2_weight_chest|image]
## Items schieben und sortieren

View File

@ -67,7 +67,7 @@ Part of the steam engine. The boiler must be connected to the cylinder via the s
### TA2 Drive Axle / TA2 Gearbox
The drive axles are used to transmit power from the steam engine to other machines. The maximum length of a drive axis is 8 blocks. With TA2 Gearboxes, larger distances can be bridged, and branches and changes of direction can be realized.
The drive axles are used to transmit power from the steam engine to other machines. The maximum length of a drive axis is 10 blocks. With TA2 Gearboxes, larger distances can be bridged, and branches and changes of direction can be realized.
[ta2_driveaxle|image]
@ -82,6 +82,31 @@ The Power Generator takes max. 25 ku of axle power and provides on the other sid
[ta2_generator|image]
## TA2 energy storage
For larger systems with several steam engines or many driven machines, an energy storage system is recommended. The energy storage at TA2 works with position energy. For this purpose, ballast (stones, gravel, sand) is pulled up in a chest with the help of a cable winch. If there is excess energy in the axis network, the chest is pulled upwards. If more energy is required in the short term than the steam engine can supply, the energy store releases the stored energy again and the weight chest moves down again.
The energy storage consists of several blocks and must be assembled as shown in the plan on the right.
In order to achieve the maximum storage capacity, the chest must be completely filled with weights and the mast including the two gear boxes must be 12 blocks high. Smaller structures are also possible.
[ta2_storage|plan]
### TA2 Winch
The cable winch must be connected to a gear box and can absorb excess energy and thus pull a weight chest upwards. The maximum rope length is 10 blocks.
[ta2_winch|image]
### TA2 Weight Chest
This chest must be placed under the winch with a distance of up to 10 blocks and filled with cobblestone, gravel or sand. If the minimum weight of a stack (99+ items) is reached and there is excess energy, the box is automatically connected to the winch via a rope and pulled up.
[ta2_weight_chest|image]
## Push and sort items

View File

@ -15,7 +15,7 @@ Das Kohlekraftwerk besteht aus mehreren Blöcken und muss wie im Plan rechts abg
Der Boiler muss mit Wasser gefüllt werden. Dazu bis zu 10 Eimer Wasser in den Boiler füllen.
Die Feuerbox muss mit Kohle oder Holzkohle gefüllt werden.
Wenn das Wasser heiß ist, kann das Ventil am Boiler geöffnet und anschließend die Generator gestartet werden.
Wenn das Wasser heiß ist, kann der Generator gestartet werden.
Das Kraftwerk kann alternativ auch mit einem Ölbrenner ausgestattet und dann mit Öl betrieben werden.
Das Öl kann über eine Pumpe und Ölleitung nachgefüllt werden.
@ -77,26 +77,46 @@ Dient zur Abkühlung des heißen Dampfs aus der Turbine. Muss über Dampfleitun
## Elektrischer Strom
In TA3 (und TA4) werden die Maschinen mit Strom angetrieben. Dazu müssen die Maschinen und Generatoren mit Stromkabel verbunden werden.
In TA3 (und TA4) werden die Maschinen mit Strom angetrieben. Dazu müssen die Maschinen, Speichersysteme und Generatoren mit Stromkabel verbunden werden.
TA3 besitzt 2 Arten von Stromkabel:
- Isolierte Kabel (TA Stromkabel) für die lokale Verkabelung im Boden oder in Gebäuden. Diese Kabel lassen sich in der Wand oder im Boden verstecken (können mit der Kelle "verputzt" werden).
- Überlandleitungen (TA Stromleitung) für Freiluftverkabelung über große Strecken. Diese Kabel sind geschützt, können also von anderen Spielern nicht entfernt werden.
Mehrere Verbraucher und Generatoren können in einem Stromnetzwerk zusammen betrieben werden. Mit Hilfe der Verteilerdosen können so große Netzwerke aufgebaut werden.
Mehrere Verbraucher, Speichersysteme und Generatoren können in einem Stromnetzwerk zusammen betrieben werden. Mit Hilfe der Verteilerdosen können so Netzwerke aufgebaut werden.
Wird zu wenig Strom bereitgestellt, gehen die Verbraucher aus.
In diesem Zusammenhang ist auch wichtig, dass die Funktionsweise von Forceload Blöcken verstanden wurde, denn bspw. Generatoren liefern nur Strom, wenn der entsprechende Map-Block geladen ist. Dies kann mit einen Forceload Block erzwungen werden.
In TA4 kommt noch ein Kabel für die Solaranlage hinzu.
[ta3_powerswitch|image]
### Bedeutung von Speichersystemen
Speichersysteme im Stromnetz erfüllen zwei Aufgaben:
- Um Bedarfsspitzen abzufangen: Alle Generatoren liefern immer gerade soviel Leistung, wie benötigt wird. Werden aber Verbraucher ein/ausgeschaltet oder kommt es aus anderen Gründen zu Bedarfsschwankungen, so können Verbraucher kurzzeitig ausfallen. Um dies zu verhindern, sollte immer mindestens ein Akkublock in jedem Netzwerk vorhanden sein. Dieser dient als Puffer und gleicht diese Schwankungen im Sekundenbereich aus.
- Um regenerative Energie zu speichern: Solar und Wind stehen nicht 24 Stunden am Tag zur Verfügung. Damit die Stromversorgung nicht ausfällt, wenn kein Strom produziert wird, müssen ein oder mehrere Speichersysteme im Netzwerk verbaut werden. Alternativ können die Lücken auch mit Öl/Kohle-Strom überbrückt werden.
Ein Speichersystem gibt seine Kapazität in kud an, also ku pro day (Tag). Bspw. ein Speichersystem mit 100 kud liefert 100 ku einen Spieltag lang, oder auch 10 ku für 10 Spieltage.
Alle TA3/TA4 Energiequellen besitzen eine einstellbare Ladecharakteristik. Standardmäßig ist diese auf "80% - 100%" eingestellt. Dies bedeutet, dass die Leistung ab 80% Füllung des Speichersystems immer weiter reduziert wird, bis sie bei 100 % komplett abschaltet. Sofern Strom im Netzwerk benötigt wird, werden die 100 % nie erreicht, da die Leistung des Generators irgendwann auf den Strombedarf im Netzwerk abgesunken ist und damit das Speichersystem nicht mehr geladen, sondern nur noch die Verbraucher bedient werden.
Dies hat mehrere Vorteile:
- Die Ladecharakteristik ist einstellbar. Damit kann man bspw. Öl/Kohle Energiequellen bei 60% und die regenerativen Energiequellen erst bei 80% zurückfahren. Damit wird nur Öl/Kohle verbrannt, wenn nicht ausreichend regenerativen Energiequellen zur Verfügung stehen.
- Mehrere Energiequellen können parallel betrieben werden und werden dabei nahezu gleichmäßig belastet, denn alle Energiequellen arbeiten bspw. bis 80% Ladekapazität des Speichersystems mit ihrer vollen Leistung und fahren dann gleichzeitig ihre Leistung zurück.
- Alle Speichersysteme in einem Netzwerk bilden einen großen Puffer. An jedem Speichersystem aber auch am Strom Terminal kann immer die Ladekapazität und der Füllungsgrad des gesamten Speichersystems in Prozent abgelesen werden.
[power_reduction|image]
### TA Stromkabel / Electric Cable
Für die lokale Verkabelung im Boden oder in Gebäuden.
Abzweigungen können mit Hilfe von Verteilerdosen realisiert werden. Die maximale Kabellänge zwischen Maschinen oder Verteilerdosen beträgt 1000 m. Es können maximale 1000 Knoten in einem Strom-Netzwerk verbunden werden. Als Knoten zählen alle Generatoren, Akkus, Verteilerdosen und Maschinen.
Abzweigungen können mit Hilfe von Verteilerdosen realisiert werden. Die maximale Kabellänge zwischen Maschinen oder Verteilerdosen beträgt 1000 m. Es können maximale 1000 Knoten in einem Strom-Netzwerk verbunden werden. Als Knoten zählen alle Blöcke mit Stromanschluss, also auch Verteilerdosen.
Da die Stromkabel nicht automatisch geschützt sind, wird für längere Strecken die Überlandleitungen (TA Stromleitung) empfohlen.
@ -113,7 +133,6 @@ Außer Kabel können auch die TA Verteilerdose und die TA Stromschalterbox verpu
### TA Verteilerdose / Electric Junction Box
Mit der Verteilerdose kann Strom in bis zu 6 Richtungen verteilt werden. Verteilerdosen können auch mit der Kelle verputzt (versteckt) und wieder sichtbar gemacht werden.
Wird mit dem TechAge Info Werkzeug (Schraubenschlüssel) auf die Verteilerdose geklickt, wird angezeigt, wie viel Leistung die Generatoren liefern bzw. die Verbraucher im Netzwerk beziehen.
[ta3_powerjunction|image]
@ -180,9 +199,9 @@ Der Stromgenerator kann nur 50 Einheiten Benzin aufnehmen. Ein zusätzlicher Tan
### TA3 Akku Block / Akku Box
Der Akku Block dient zur Speicherung von überschüssiger Energie und gibt bei Stromausfall automatisch Strom ab (soweit vorhanden).
Der Akku Block ist eine sekundäre Stromquelle. Das bedeutet, bei Strombedarf werden zuerst die Generatoren genutzt. Nur wenn der Strom im Netz nicht ausreicht, springt der Akku Block ein. Das Gleiche gilt auch für die Stromaufnahme. Daher kann auch kein Akku mit einem anderen Akku geladen werden.
Der Akku liefert 10 ku bzw. nimmt 10 ku auf.
Bei Volllast kann ein Akku 400 s lang Strom aufnehmen und wenn er voll ist, auch wieder abgeben. Dies entspricht 8 h Spielzeit bei einem normalen Spieltag von 20 min.
Mehrere Akku Blocks zusammen bilden ein TA3 Energiespeichersystem. Jeder Akku Block hat eine Anzeige für den Ladezustand und für die gespeicherte Ladung, wobei hier immer die Werte für das gesamte Netzwerk angezeigt werden. Die gespeicherte Ladung wird in "kud" also "ku-days" angezeigt (analog zu kWh) 5 kud entspricht damit bspw. 5 ku für einen Spieltag (20 min) oder 1 ku für 5 Spieltage.
Ein Akku Block hat 3.33 kud.
[ta3_akkublock|image]
@ -191,9 +210,16 @@ Bei Volllast kann ein Akku 400 s lang Strom aufnehmen und wenn er voll ist, auch
Das Strom-Terminal muss mit dem Stromnetz verbunden werden. Es zeigt Daten aus dem Stromnetz an.
In der oberen Hälfte werden nur die Daten eines ausgewählten Typs ausgegeben. Wird als Typ bspw. "Kraftwerk" gewählt, so werden nur die Daten von Öl- und Kohlekraftwerken gesammelt und ausgegeben. Links werden die Daten von Generatoren (Stromabgabe) und rechts die Daten von Energiespeichern (Stromaufnahme) ausgegeben. Beim Akkublocks bspw. wird beides ausgegeben, da der Akku Strom aufnehmen und abgeben kann.
In der oberen Hälfte werden die wichtigsten Größen ausgegeben:
In der unteren Hälfte werden die Daten aller Generatoren und Speichersystemen des ganzen Stromnetzen zusammengefasst ausgegeben.
- aktuelle/maximale Generatorleistung
- aktueller Stromaufnahme aller Verbraucher
- aktueller Ladestrom in/aus dem Speichersystems
- aktuellen Ladezustand des Speichersystems in Prozent
In der unteren Hälfte wird die Anzahl der Netzwerkblöcke ausgegeben.
Über den Reiter "console" können weitere Daten zu den Generatoren und Speichersystemen abgefragt werden.
[ta3_powerterminal|image]
@ -208,16 +234,6 @@ Das Elektromotor nimmt primär max. 40 ku an Strom auf und gibt sekundär max. 3
[ta3_motor|image]
### TA3 Strom Terminal / Power Terminal
Das Strom-Terminal muss mit dem Stromnetz verbunden werden. Es zeigt Daten aus dem Stromnetz an.
In der oberen Hälfte werden nur die Daten eines ausgewählten Typs ausgegeben. Wird als Typ bspw. "Kraftwerk" gewählt, so werden nur die Daten von Öl- und Kohlekraftwerken gesammelt und ausgegeben. Links werden die Daten von Generatoren (Stromabgabe) und rechts die Daten von Energiespeichern (Stromaufnahme) ausgegeben. Beim Akkublocks bspw. wird beides ausgegeben, da der Akku Strom aufnehmen und abgeben kann.
In der unteren Hälfte werden die Daten aller Generatoren und Speichersystemen des ganzen Stromnetzen zusammengefasst ausgegeben.
[ta3_powerterminal|image]
## TA3 Industrieofen
@ -801,11 +817,14 @@ Die Verarbeitungsleistung beträgt bis zu 8 mal ein Item alle 4 Sekunden.
Das Techage Info Tool (Schraubenschlüssel) hat verschiedene Funktionen. Er zeigt die Uhrzeit, die Position, die Temperatur und das Biome an, wenn auf einen unbekannten Block geklickt wird.
Wird auf einen TechAge Block mit Kommandoschnittstelle geklickt, werden alle verfügbaren Daten abgerufen (siehe auch "Logik-/Schalt-Blöcke").
Bei Strom-Verteilerdosen werden die benachbarten Netzwerkteilnehmer (bis zu 50 Meter weit) mit einem blauen Käfig angezeigt.
Mit Shift+Rechtsklick kann bei einigen Blöcken ein erweitertes Menü geöffnet werden. Hier lassen sich je nach Block weitere Daten abrufen oder spezielle Einstellungen vornehmen. Bei einem Generator kann bspw. die Ladekurve/abschaltung programmiert werden.
[ta3_end_wrench|image]
### TechAge Programmer
Mit dem Programmer können Blocknummern mit einem Rechtsklick von mehreren Blöcken eingesammelt und mit einem Linksklick in einen Block wie Taster/Schalter geschrieben werden.

View File

@ -77,13 +77,13 @@ Used to cool the hot steam from the turbine. Must be connected to the boiler and
## Electrical current
In TA3 (and TA4) the machines are powered by electricity. To do this, the machines and generators must be connected with power cables.
In TA3 (and TA4) the machines are powered by electricity. To do this, machines, storage systems, and generators must be connected with power cables.
TA3 has 2 types of power cables:
- Insulated cables (TA power cables) for local wiring in the floor or in buildings. These cables can be hidden in the wall or in the floor (can be "plastered" with the trowel).
- Overland lines (TA power line) for outdoor cabling over long distances. These cables are protected and cannot be removed by other players.
Several consumers and generators can be operated together in a power network. Large networks can be set up with the help of the junction boxes.
Several consumers, storage systems, and generators can be operated together in a power network. Networks can be set up with the help of the junction boxes.
If too little electricity is provided, consumers run out.
In this context, it is also important that the functionality of Forceload blocks is understood, because generators, for example, only supply electricity when the corresponding map block is loaded. This can be enforced with a forceload block.
@ -93,10 +93,31 @@ In TA4 there is also a cable for the solar system.
[ta3_powerswitch|image]
### Importance of storage systems
Storage systems in the power grid fulfill two tasks:
- To cope with peaks in demand: All generators always deliver just as much power as is needed. However, if consumers are switched on/off or there are fluctuations in demand for other reasons, consumers can fail for a short time. To prevent this, there should always be at least one battery block in every network. This serves as a buffer and compensates for these fluctuations in the seconds range.
- To store regenerative energy: Solar and wind are not available 24 hours a day. So that the power supply does not fail when no electricity is produced, one or more storage systems must be installed in the network. Alternatively, the gaps can also be bridged with oil/coal electricity.
A storage system indicates its capacity in kud, i.e. ku per day. For example, a storage system with 100 kud delivers 100 ku for one game day, or 10 ku for 10 game days.
All TA3/TA4 energy sources have adjustable charging characteristics. By default this is set to "80% - 100%". This means that when the storage system is 80% full, the output is reduced further and further until it switches off completely at 100%. If electricity is required in the network, 100% will never be reached, since the power of the generator has at some point dropped to the electricity demand in the network and the storage system is no longer charged, but only the consumers are served.
This has several advantages:
- The charging characteristics are adjustable. This means, for example, that oil/coal energy sources can be reduced at 60% and regenerative energy sources only at 80%. This means that oil/coal is only burned if there are not enough renewable energy sources available.
- Several energy sources can be operated in parallel and are loaded almost evenly, because all energy sources work, for example, up to 80% of the storage system's charging capacity at their full capacity and then reduce their capacity at the same time.
- All storage systems in a network form a large buffer. The charging capacity and the filling level of the entire storage system can always be read in percent on every storage system, but also on the electricity terminal.
[power_reduction|image]
### TA Electric Cable
For local wiring in the floor or in buildings.
Branches can be realized using junction boxes. The maximum cable length between machines or junction boxes is 1000 m. A maximum of 1000 nodes can be connected in a power network. All generators, batteries, junction boxes and machines count as nodes.
Branches can be realized using junction boxes. The maximum cable length between machines or junction boxes is 1000 m. A maximum of 1000 nodes can be connected in a power network. All blocks with power connection, including junction boxes, count as nodes.
Since the power cables are not automatically protected, the land lines (TA power line) are recommended for longer distances.
@ -113,7 +134,6 @@ In addition to cables, the TA junction box and the TA power switch box can also
### TA Electric Junction Box
With the junction box, electricity can be distributed in up to 6 directions. Junction boxes can also be plastered (hidden) with a trowel and made visible again.
If the TechAge Info tool (wrench) is clicked on the junction box, it is shown whether the power line is powered or not.
[ta3_powerjunction|image]
@ -180,9 +200,10 @@ The power generator can only hold 50 units of gasoline. An additional tank and a
### TA3 Battery Block
The battery block is used to store excess energy and automatically delivers power in the event of a power failure (if available).
The battery block is a secondary power source. This means that the generators are used first when electricity is required. The battery block will only provide power if there is insufficient electricity in the network. The same applies to the current consumption. Therefore, no battery can be charged with another battery.
The battery delivers 10 ku or takes up 10 ku.
At full load, a battery can take up to 400 s of current and, when it is full, also release it again. This corresponds to 8 hours of playing time on a normal game day of 20 minutes.
Several battery blocks together form a TA3 energy storage system. Each battery block has a display for the charging state and for the stored load.
The values for the entire network are always displayed here. The stored load is displayed in "kud" or "ku-days" (analogous to kWh) 5 kud thus corresponds, for example, to 5 ku for a game day (20 min) or 1 ku for 5 game days.
A battery block has 3.33 kud
[ta3_akkublock|image]
@ -191,9 +212,16 @@ At full load, a battery can take up to 400 s of current and, when it is full, al
The power terminal must be connected to the power grid. It shows data from the power grid.
Only the data of a selected type are output in the upper half. If, for example, "Power station" is selected as the type, only the data from oil and coal-fired power stations are collected and output. The data from generators (power delivery) and the data from energy storage devices (power consumption) are output on the left. In the case of the battery blocl, for example, both are output because the battery can draw and deliver power.
The most important figures are displayed in the upper half:
In the lower half, the data of all generators and storage systems of the entire electricity network are summarized.
- current/maximum generator power
- current power consumption of all consumers
- current charging current in/from the storage system
- Current state of charge of the storage system in percent
The number of network blocks is output in the lower half.
Additional data on the generators and storage systems can be queried via the "console" tab.
[ta3_powerterminal|image]
@ -784,7 +812,8 @@ The processing power is up to 8 times one item every 4 seconds.
The Techage Info Tool (wrench) has several functions. It shows the time, position, temperature and biome when an unknown block is clicked on.
If you click on a TechAge block with command interface, all available data will be shown (see also "Logic / switching blocks").
In the case of power junction boxes, the neighboring network participants (up to 50 meters away) are displayed with a blue cage.
With Shift + right click an extended menu can be opened for some blocks. Depending on the block, further data can be called up or special settings can be made here. In the case of a generator, for example, the charging curve/switch-off can be programmed.
[ta3_end_wrench|image]

View File

@ -23,9 +23,7 @@ Die Windkraftanlage liefert eine Leistung von 70 ku, aber dies nur 8 Stunden am
### TA4 Windkraftanlage / Wind Turbine
Der Windkraftanlagenblock (Rotor) ist das Herzstück der Windkraftanlage. Dieser Block muss oben auf den Mast gesetzt werden. Idealerweise auf Y = 15, dann bleibst du noch gerade innerhalb eines Map-/Forceload-Blocks.
Nach dem Setzen des Blocks wird ein Check durchgeführt, ob alle Bedingungen für den Betrieb der Windkraftanlage erfüllt sind. Sofern alle Bedingungen erfüllt sind, erscheinen beim Setzen dieses Blocks auch automatisch die Rotorblätter (Flügel). Anderenfalls wird dir eine Fehlermeldung angezeigt.
Durch Schlagen auf den Block kann der Check wiederholt werden.
Beim Starten der Windkraftanlage werden alle Bedingungen für den Betrieb der Windkraftanlage überprüft. Sofern alle Bedingungen erfüllt sind, erscheinen auch automatisch die Rotorblätter (Flügel). Anderenfalls wird eine Fehlermeldung angezeigt.
[ta4_windturbine|image]
@ -131,11 +129,13 @@ Diese Solarzelle kann nicht mit den anderen Solarmodulen kombiniert werden.
## Energiespeicher
Der TA4 Energiespeicher ersetzt den Batterie Block aus TA3.
Der Energiespeicher besteht aus einer Betonhülle (Concrete Block) gefüllt mit Gravel. Es gibt 3 Größen vom Speicher:
- Hülle mit 5x5x5 Concrete Blocks, gefüllt mit 27 Gravel, Speicherkapazität: 1/2 Tag bei 60 ku
- Hülle mit 7x7x7 Concrete Blocks, gefüllt mit 125 Gravel, Speicherkapazität: 2,5 Tage bei 60 ku
- Hülle mit 9x9x9 Concrete Blocks, gefüllt mit 343 Gravel, Speicherkapazität: 6,5 Tage bei 60 ku
- Hülle mit 5x5x5 Concrete Blocks, gefüllt mit 27 Gravel, Speicherkapazität: 22.5 kud
- dHülle mit 7x7x7 Concrete Blocks, gefüllt mit 125 Gravel, Speicherkapazität: 104 kud
- Hülle mit 9x9x9 Concrete Blocks, gefüllt mit 343 Gravel, Speicherkapazität: 286 kud
In der Betonhülle darf ein Fenster aus einem Obsidian Glas Block sein. Dieses muss ziemlich in der Mitte der Wand platziert werden. Durch dieses Fenster sieht man, ob der Speicher mehr als 80 % geladen ist. Im Plan rechts sieht man den Aufbau aus TA4 Wärmetauscher bestehend aus 3 Blöcken, der TA4 Turbine und dem TA4 Generator. Beim Wärmetauscher ist auf die Ausrichtung zu achten (der Pfeil bei Block 1 muss zur Turbine zeigen).
@ -143,7 +143,6 @@ Entgegen dem Plan rechts müssen die Anschlüsse am Speicherblock auf gleicher E
Sowohl der Generator als auch der Wärmetauscher haben einen Stromanschluss und müssen mit dem Stromnetz verbunden werden.
Im Prinzip arbeitet das das Wärmespeichersystem genau gleich wie die Akkus, nur mit viel mehr Speicherkapazität.
Der Wärmespeicher kann 60 ku aufnehmen und abgeben.
Damit das Wärmespeichersystem funktioniert, müssen alle Blöcke (auch Betonhülle und Gravel) mit Hilfe eines Forceloadblockes geladen sein.
@ -153,7 +152,7 @@ Damit das Wärmespeichersystem funktioniert, müssen alle Blöcke (auch Betonhü
### TA4 Wärmetauscher / Heat Exchanger
Der Wärmetauscher besteht aus 3 Teilen, die aufeinander gesetzt werden müssen, wobei der Pfeil des ersten Blockes Richtung Turbine zeigen muss. Die Rohrleitungen müssen mit den gelben TA4 Röhren aufgebaut werden.
Der Wärmetauscher muss am Stromnetz angeschlossen werden. Der Wärmetauscher lädt den Energiespeicher wieder auf, wenn ausreichend Strom zur Verfügung steht und der Energiespeicher weniger als 95 % geladen ist. Der Wärmetauscher nimmt dabei 60 ku auf.
Der Wärmetauscher muss am Stromnetz angeschlossen werden. Über den Wärmetauscher wird der Energiespeicher wieder aufgeladen, sofern ausreichend Strom zur Verfügung steht.
[ta4_heatexchanger|image]
@ -167,9 +166,9 @@ Die Turbine ist Teil des Energiespeichers. Sie muss neben den Generator gesetzt
### TA4 Generator
Der Generator dient zur Stromerzeugung. Daher muss auch der Generator am Stromnetz angeschlossen werden.
Der Generator ist Teil des Energiespeichers. Er dient zur Stromerzeugung und gibt damt die Energie des Energiespeichers wieder ab. Daher muss auch der Generator am Stromnetz angeschlossen werden.
Der Generator kann 60 ku abgeben.
Wichtig: Wärmetauscher und Generator müssen mit ein und demselben Stromnetz verbunden sein!
[ta4_generator|image]
@ -190,6 +189,52 @@ Die maximale Leitungslänge beträgt 100 m.
[ta4_pipe|image]
## Stromverteilung
Mit Hilfe von Stromkabeln und Verteilerdosen können Stromnetze von bis zu 1000 Blöcke/Knoten aufgebaut werden. Hierbei ist aber zu beachten, dass Verteilerdosen auch mitgezählt werden müssen. Somit können bis zu 500 Generatoren/Speichersysteme/Maschinen/Lampen an einem Stromnetz hängen.
Mit Hilfe von Trenntransformator und Stromzähler können Netzwerke zu noch größeren Strukturen verbunden werden.
[ta4_transformer|image]
### TA4 Trenntransformator / TA4 Isolation Transformer
Mit Hilfe eines Trenntransformators können zwei Stromnetze zu einem größeren Netzwerk verbunden werden. Der Trenntransformator kann Strom in beide Richtungen übertragen.
Der Trenntransformator kann bis zu 100 ku übertragen.
[ta4_transformer|image]
### TA4 Stromzähler / TA4 Electric Meter
Mit Hilfe eines Stromzählers können zwei Stromnetze zu einem größeren Netzwerk verbunden werden. Der Stromzähler leitet den Strom nur in eine Richtungen weiter (Pfeil beachten). Die Menge an Strom (in kud) wird gemessen und angezeigt. Die Strommenge kann auch über das Kommando `consumption` durch einen Lua Controller abgefragt werden.
Der Stromzähler kann bis zu 200 ku durchleiten.
[ta4_electricmeter|image]
### TA4 Laser
Der TA4 Laser dient zur kabellosen Stromübertagung. Dazu sind zwei Blöcke notwendig: TA4 Laserstrahl Sender und TA4 Laserstrahl Empfänger. Zwischen beiden Blöcken muss sich eine Luftstrecke befinden, so dass der Laserstrahl vom Sender bis zum Empfänger aufgebaut werden kann.
Zuerst muss der Sender platziert werden. Dieser schaltet sofort den Laserstahls ein und zeigt damit mögliche Positionen des Empfängers an. Mögliche Positionen für den Empfänger werden auch über eine Chat-Nachricht ausgegeben. Mit dem Laser lassen sich Strecken bis 96 Blöcke überbrücken.
Ist die Verbindung aufgebaut (es muss dazu noch kein Strom fließen), wird dies über den Info-Text des Senders und auch des Empfängers angezeigt.
Die Laserblöcke selbst benötigen keinen Strom.
[ta4_laser|image]
## Wasserstoff
Strom kann mittels Elektrolyse in Wasserstoff und Sauerstoff aufgespalten werden. Auf der anderen Seite kann über eine Brennstoffzelle Wasserstoff mit Sauerstoff aus der Luft wieder in Strom umgewandelt werden.
@ -211,6 +256,8 @@ Es muss von links mit Strom versorgt werden. Rechts kann Wasserstoff über Röhr
Der Elektrolyseur kann bis zu 35 ku an Strom aufnehmen und generiert dann alle 4 s ein Wasserstoff Item.
In den Elektrolyseur passen 200 Einheiten Wasserstoff.
Der Elektrolyseur besitzt ein Schraubenschlüssel-Menü zur Einstellung der Stromaufnahme und des Abschaltpunkts.
[ta4_electrolyzer|image]
@ -683,14 +730,3 @@ Die Verarbeitungsleistung beträgt ein Item alle 8 s. Der Block benötigt hierf
[ta4_recycler|image]
### TA4 Laser
Der TA4 Laser dient zur kabellosen Stromübertagung. Dazu sind zwei Blöcke notwendig: TA4 Laserstrahl Sender und TA4 Laserstrahl Empfänger. Zwischen beiden Blöcken muss sich eine Luftstrecke befinden, so dass der Laserstrahl vom Sender bis zum Empfänger aufgebaut werden kann.
Zuerst muss der Sender platziert werden. Dieser schaltet sofort den Laserstahls ein und zeigt damit mögliche Positionen des Empfängers an. Mögliche Positionen für den Empfänger werden auch über eine Chat-Nachricht ausgegeben. Mit dem Laser lassen sich Strecken bis 96 Blöcke überbrücken.
Ist die Verbindung aufgebaut (es muss dazu noch kein Strom fließen), wird dies über den Info-Text des Senders und auch des Empfängers angezeigt.
Die Laserblöcke selbst benötigen keinen Strom.
[ta4_laser|image]t

View File

@ -23,9 +23,7 @@ The wind turbine delivers 70 ku, but only 8 hours a day (see above).
### TA4 Wind Turbine
The wind turbine block (rotor) is the heart of the wind turbine. This block must be placed on top of the mast. Ideally at Y = 15, then you just stay within a map / forceload block.
After the block has been set, a check is carried out to determine whether all conditions for the operation of the wind turbine have been met. If all conditions are met, the rotor blades (wings) appear automatically when this block is set. Otherwise you will get an error message.
The check can be repeated by hitting the block.
When you start the turbine, all conditions for the operation of the wind turbine are checked. If all conditions are met, the rotor blades (wings) appear automatically. Otherwise you will get an error message.
[ta4_windturbine|image]
@ -131,11 +129,13 @@ This solar cell cannot be combined with the other solar modules.
## Thermal Energy Storage
The thermal energy storage replaces the battery block from TA3.
The thermal energy store consists of a concrete shell (concrete blocks) filled with gravel. Three sizes of the storage are possible:
- Cover with 5x5x5 concrete blocks, filled with 27 gravel, storage capacity: 1/2 day at 60 ku
- Cover with 7x7x7 concrete blocks, filled with 125 gravel, storage capacity: 2.5 days at 60 ku
- Cover with 9x9x9 concrete blocks, filled with 343 gravel, storage capacity: 6.5 days at 60 ku
- Cover with 5x5x5 concrete blocks, filled with 27 gravel, storage capacity: 22.5 kud
- Cover with 7x7x7 concrete blocks, filled with 125 gravel, storage capacity: 104 kud
- Cover with 9x9x9 concrete blocks, filled with 343 gravel, storage capacity: 286 kud
A window made of an obsidian glass block may be in the concrete shell. This must be placed fairly in the middle of the wall. Through this window you can see whether the storage is loaded more than 80%. In the plan on the right you can see the structure of TA4 heat exchanger consisting of 3 blocks, the TA4 turbine and the TA4 generator. Pay attention to the alignment of the heat exchanger (the arrow at block 1 must point to the turbine).
@ -143,7 +143,6 @@ Contrary to the plan on the right, the connections on the storage block must be
Both the generator and the heat exchanger have a power connection and must be connected to the power grid.
In principle, the heat storage system works exactly the same as the batteries, only with much more storage capacity.
The heat accumulator can hold and deliver 60 ku.
In order for the heat storage system to work, all blocks (also the concrete shell and gravel) must be loaded using a forceload block.
@ -153,7 +152,7 @@ In order for the heat storage system to work, all blocks (also the concrete shel
### TA4 Heat Exchanger
The heat exchanger consists of 3 parts that must be placed on top of each other, with the arrow of the first block pointing towards the turbine. The pipes must be built with the yellow TA4 pipes.
The heat exchanger must be connected to the power grid. The heat exchanger charges the energy store again when sufficient electricity is available and the energy storage is less than 95% charged. The heat exchanger takes up 60 ku.
The heat exchanger must be connected to the power grid. The energy storage device is recharged via the heat exchanger, provided that sufficient electricity is available.
[ta4_heatexchanger|image]
@ -168,8 +167,9 @@ The turbine is part of the energy storage. It must be placed next to the generat
### TA4 Generator
The generator is used to generate electricity. Therefore, the generator must also be connected to the power grid.
The generator is part of the energy storage. It is used to generate electricity and thus releases the energy from the energy storage unit. Therefore, the generator must also be connected to the power grid.
The generator can deliver 60 ku.
Important: Both, heat exchanger and generator must be connected to the same power grid!
[ta4_generator|image]
@ -190,6 +190,44 @@ The maximum cable length is 100 m.
[ta4_pipe|image]
## Power Distribution
With the help of power cables and junction boxes, power networks of up to 1000 blocks/nodes can be set up. However, it should be noted that distribution boxes must also be counted. This means that up to 500 generators/storage systems/machines/lamps can be connected to a power grid.
With the help of an isolating transformer and electricity meter, networks can be connected to form even larger structures.
[ta4_transformer|image]
### TA4 Isolation Transformer
With the help of an isolating transformer, two power grids can be connected to form a larger network. The isolation transformer can transmit electricity in both directions.
The isolation transformer can transmit up to 100 ku.
[ta4_transformer|image]
### TA4 Electric Meter
With the help of an electricity meter, two electricity networks can be connected to form a larger network. The electricity meter only transmits electricity in one direction (note arrow). The amount of electricity (in kud) is measured and displayed. The amount of electricity can also be queried by a Lua controller using the `consumption` command.
The electricity meter can pass up to 200 ku.
[ta4_electricmeter|image]
### TA4 Laser
The TA4 laser is used for wireless power transmission. Two blocks are required for this: TA4 Laser Beam Emitter and TA4 Laser Beam Receiver. There must be an air gap between the two blocks so that the laser beam can be built up from the emitter to the receiver. First the emitter must be placed. This immediately switches on the laser beam and shows possible positions of the receiver. Possible positions for the receiver are also output via a chat message.
With the laser, distances of up to 96 blocks can be bridged. Once the connection has been established (no current has to flow), this is indicated via the info text of the emitter and also of the receiver.
The laser blocks themselves do not require any electricity.
[ta4_laser|image]
## Hydrogen
Electrolysis can be used to split electricity into hydrogen and oxygen. On the other hand, hydrogen can be converted back into electricity with oxygen from the air using a fuel cell.
@ -211,6 +249,8 @@ It must be powered from the left. On the right, hydrogen can be extracted via pi
The electrolyzer can draw up to 35 ku of electricity and then generates a hydrogen item every 4 s.
200 units of hydrogen fit into the electrolyzer.
The electrolyzer has a wrench menu for setting the current consumption and the switch-off point.
[ta4_electrolyzer|image]
@ -683,13 +723,3 @@ The machine can disassemble pretty much any Techage and Hyperloop blocks. But no
The processing power is one item every 8 s. The block requires 16 ku of electricity for this.
[ta4_recycler|image]
### TA4 Laser
The TA4 laser is used for wireless power transmission. Two blocks are required for this: TA4 Laser Beam Emitter and TA4 Laser Beam Receiver. There must be an air gap between the two blocks so that the laser beam can be built up from the emitter to the receiver. First the emitter must be placed. This immediately switches on the laser beam and shows possible positions of the receiver. Possible positions for the receiver are also output via a chat message.
With the laser, distances of up to 96 blocks can be bridged. Once the connection has been established (no current has to flow), this is indicated via the info text of the emitter and also of the receiver.
The laser blocks themselves do not require any electricity.
[ta4_laser|image]

View File

@ -2,6 +2,8 @@
- [Tech Age Mod](./manual_DE.md#tech-age-mod)
- [Hinweise](./manual_DE.md#hinweise)
- [Änderungen ab Version 1.0](./manual_DE.md#änderungen-ab-version-1.0)
- [Tipps zur Umstellung](./manual_DE.md#tipps-zur-umstellung)
- [Erze und Mineralien](./manual_DE.md#erze-und-mineralien)
- [Meridium](./manual_DE.md#meridium)
- [Usmium](./manual_DE.md#usmium)
@ -9,7 +11,6 @@
- [Erdöl](./manual_DE.md#erdöl)
- [Bauxit](./manual_DE.md#bauxit)
- [Basalt](./manual_DE.md#basalt)
- [History](./manual_DE.md#history)
- [TA1: Eisenzeitalter](./manual_ta1_DE.md#ta1:-eisenzeitalter)
- [Köhler / Coal Pile](./manual_ta1_DE.md#köhler--coal-pile)
- [Kohlebrenner / Coal Burner](./manual_ta1_DE.md#kohlebrenner--coal-burner)
@ -28,6 +29,9 @@
- [TA2 Dampfleitungen / Steam Pipe](./manual_ta2_DE.md#ta2-dampfleitungen--steam-pipe)
- [TA2 Antriebsachsen / TA2 Drive Axle](./manual_ta2_DE.md#ta2-antriebsachsen--ta2-drive-axle)
- [TA2 Stromgenerator / TA2 Power Generator](./manual_ta2_DE.md#ta2-stromgenerator--ta2-power-generator)
- [TA2 Energiespeicher](./manual_ta2_DE.md#ta2-energiespeicher)
- [TA2 Seilwinde / TA2 Winch](./manual_ta2_DE.md#ta2-seilwinde---ta2-winch)
- [TA2 Gewichtekiste / TA2 Weight Chest](./manual_ta2_DE.md#ta2-gewichtekiste--ta2-weight-chest)
- [Items schieben und sortieren](./manual_ta2_DE.md#items-schieben-und-sortieren)
- [Röhren / TechAge Tube](./manual_ta2_DE.md#röhren--techage-tube)
- [Röhren Konzentrator / Tube Concentrator](./manual_ta2_DE.md#röhren-konzentrator--tube-concentrator)
@ -55,6 +59,7 @@
- [TA3 Generator](./manual_ta3_DE.md#ta3-generator)
- [TA3 Kühler / Cooler](./manual_ta3_DE.md#ta3-kühler--cooler)
- [Elektrischer Strom](./manual_ta3_DE.md#elektrischer-strom)
- [Bedeutung von Speichersystemen](./manual_ta3_DE.md#bedeutung-von-speichersystemen)
- [TA Stromkabel / Electric Cable](./manual_ta3_DE.md#ta-stromkabel--electric-cable)
- [TA Verteilerdose / Electric Junction Box](./manual_ta3_DE.md#ta-verteilerdose--electric-junction-box)
- [TA Stromleitung / Power Line](./manual_ta3_DE.md#ta-stromleitung--power-line)
@ -68,7 +73,6 @@
- [TA3 Akku Block / Akku Box](./manual_ta3_DE.md#ta3-akku-block---akku-box)
- [TA3 Strom Terminal / Power Terminal](./manual_ta3_DE.md#ta3-strom-terminal--power-terminal)
- [TA3 Elektromotor / TA3 Electric Motor](./manual_ta3_DE.md#ta3-elektromotor--ta3-electric-motor)
- [TA3 Strom Terminal / Power Terminal](./manual_ta3_DE.md#ta3-strom-terminal--power-terminal)
- [TA3 Industrieofen](./manual_ta3_DE.md#ta3-industrieofen)
- [TA3 Ofen-Ölbrenner / Furnace Oil Burner](./manual_ta3_DE.md#ta3-ofen-ölbrenner--furnace-oil-burner)
- [TA3 Ofenoberteil / Furnace Top](./manual_ta3_DE.md#ta3-ofenoberteil--furnace-top)
@ -145,6 +149,10 @@
- [TA4 Generator](./manual_ta4_DE.md#ta4-generator)
- [TA4 Rohrzulauf / TA4 Pipe Inlet](./manual_ta4_DE.md#ta4-rohrzulauf--ta4-pipe-inlet)
- [TA4 Röhre / Pipe](./manual_ta4_DE.md#ta4-röhre--pipe)
- [Stromverteilung](./manual_ta4_DE.md#stromverteilung)
- [TA4 Trenntransformator / TA4 Isolation Transformer](./manual_ta4_DE.md#ta4-trenntransformator--ta4-isolation-transformer)
- [TA4 Stromzähler / TA4 Electric Meter](./manual_ta4_DE.md#ta4-stromzähler--ta4-electric-meter)
- [TA4 Laser](./manual_ta4_DE.md#ta4-laser)
- [Wasserstoff](./manual_ta4_DE.md#wasserstoff)
- [Elektrolyseur](./manual_ta4_DE.md#elektrolyseur)
- [Brennstoffzelle](./manual_ta4_DE.md#brennstoffzelle)
@ -195,5 +203,4 @@
- [TA4 Steinbrecher / Quarry](./manual_ta4_DE.md#ta4-steinbrecher--quarry)
- [TA4 Elektronikfabrik / Electronic Fab](./manual_ta4_DE.md#ta4-elektronikfabrik--electronic-fab)
- [TA4 Injektor / Injector](./manual_ta4_DE.md#ta4-injektor--injector)
- [TA4 Recycler](./manual_ta4_DE.md#ta4-recycler)
- [TA4 Laser](./manual_ta4_DE.md#ta4-laser)
- [TA4 Recycler](./manual_ta4_DE.md#ta4-recycler)

View File

@ -2,6 +2,8 @@
- [Tech Age Mod](./manual_EN.md#tech-age-mod)
- [Hints](./manual_EN.md#hints)
- [Changes from version 1.0](./manual_EN.md#changes-from-version-1.0)
- [Tips on switching](./manual_EN.md#tips-on-switching)
- [Ores and Minerals](./manual_EN.md#ores-and-minerals)
- [Meridium](./manual_EN.md#meridium)
- [Usmium](./manual_EN.md#usmium)
@ -28,6 +30,9 @@
- [TA2 Steam Pipes](./manual_ta2_EN.md#ta2-steam-pipes)
- [TA2 Drive Axle / TA2 Gearbox](./manual_ta2_EN.md#ta2-drive-axle--ta2-gearbox)
- [TA2 Power Generator](./manual_ta2_EN.md#ta2-power-generator)
- [TA2 energy storage](./manual_ta2_EN.md#ta2-energy-storage)
- [TA2 Winch](./manual_ta2_EN.md#ta2-winch)
- [TA2 Weight Chest](./manual_ta2_EN.md#ta2-weight-chest)
- [Push and sort items](./manual_ta2_EN.md#push-and-sort-items)
- [TechAge Tube](./manual_ta2_EN.md#techage-tube)
- [Tube Concentrator](./manual_ta2_EN.md#tube-concentrator)
@ -55,6 +60,7 @@
- [TA3 generator](./manual_ta3_EN.md#ta3-generator)
- [TA3 cooler](./manual_ta3_EN.md#ta3-cooler)
- [Electrical current](./manual_ta3_EN.md#electrical-current)
- [Importance of storage systems](./manual_ta3_EN.md#importance-of-storage-systems)
- [TA Electric Cable](./manual_ta3_EN.md#ta-electric-cable)
- [TA Electric Junction Box](./manual_ta3_EN.md#ta-electric-junction-box)
- [TA Power Line](./manual_ta3_EN.md#ta-power-line)
@ -144,6 +150,10 @@
- [TA4 Generator](./manual_ta4_EN.md#ta4-generator)
- [TA4 Pipe Inlet](./manual_ta4_EN.md#ta4-pipe-inlet)
- [TA4 Pipe](./manual_ta4_EN.md#ta4-pipe)
- [Power Distribution](./manual_ta4_EN.md#power-distribution)
- [TA4 Isolation Transformer](./manual_ta4_EN.md#ta4-isolation-transformer)
- [TA4 Electric Meter](./manual_ta4_EN.md#ta4-electric-meter)
- [TA4 Laser](./manual_ta4_EN.md#ta4-laser)
- [Hydrogen](./manual_ta4_EN.md#hydrogen)
- [Electrolyzer](./manual_ta4_EN.md#electrolyzer)
- [Fuel Cell](./manual_ta4_EN.md#fuel-cell)
@ -194,5 +204,4 @@
- [TA4 Quarry](./manual_ta4_EN.md#ta4-quarry)
- [TA4 Electronic Fab](./manual_ta4_EN.md#ta4-electronic-fab)
- [TA4 Injector](./manual_ta4_EN.md#ta4-injector)
- [TA4 Recycler](./manual_ta4_EN.md#ta4-recycler)
- [TA4 Laser](./manual_ta4_EN.md#ta4-laser)
- [TA4 Recycler](./manual_ta4_EN.md#ta4-recycler)

View File

@ -1,4 +1,4 @@
name = techage
depends = default,doors,flowers,tubelib2,basic_materials,bucket,stairs,screwdriver,minecart,lcdlib,safer_lua
depends = default,doors,flowers,tubelib2,networks,basic_materials,bucket,stairs,screwdriver,minecart,lcdlib,safer_lua
optional_depends = unified_inventory,wielded_light,unifieddyes,moreores,ethereal,mesecon,digtron,bakedclay,moreblocks
description = Techage, go through 4 tech ages in search of wealth and power!

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -17,8 +17,7 @@ local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local Pipe = techage.LiquidPipe
local networks = techage.networks
local liquid = techage.liquid
local liquid = networks.liquid
local function orientation(pos, names)
@ -40,10 +39,6 @@ local function after_place_node(pos, placer)
Pipe:after_place_node(pos)
end
local function tubelib2_on_update2(pos, dir, tlib2, node)
liquid.update_network(pos, dir, tlib2)
end
local function after_dig_node(pos, oldnode, oldmetadata, digger)
Pipe:after_dig_node(pos)
end
@ -73,9 +68,7 @@ minetest.register_node("techage:ta3_distiller_base", {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, 1/2, 1/2},
},
after_place_node = after_place_node,
tubelib2_on_update2 = tubelib2_on_update2,
after_dig_node = after_dig_node,
paramtype2 = "facedir",
@ -83,15 +76,10 @@ minetest.register_node("techage:ta3_distiller_base", {
groups = {cracky=2},
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
networks = {
pipe2 = {
sides = {B=1}, -- Pipe connection sides
ntype = "pump",
},
},
})
liquid.register_nodes({"techage:ta3_distiller_base"}, Pipe, "pump", {"B"}, {})
minetest.register_node("techage:ta3_distiller1", {
description = S("TA3 Distillation Tower 1"),
tiles = {"techage_distiller1.png"},
@ -112,8 +100,6 @@ minetest.register_node("techage:ta3_distiller1", {
after_place_node(pos, placer)
return res
end,
tubelib2_on_update2 = tubelib2_on_update2,
after_dig_node = after_dig_node,
paramtype = "light",
@ -122,15 +108,10 @@ minetest.register_node("techage:ta3_distiller1", {
groups = {cracky=2},
is_ground_content = false,
sounds = default.node_sound_metal_defaults(),
networks = {
pipe2 = {
sides = {F=1}, -- Pipe connection sides
ntype = "tank",
},
},
})
liquid.register_nodes({"techage:ta3_distiller1"}, Pipe, "pump", {"F"}, {})
minetest.register_node("techage:ta3_distiller2", {
description = S("TA3 Distillation Tower 2"),
tiles = {"techage_distiller2.png"},
@ -175,8 +156,6 @@ minetest.register_node("techage:ta3_distiller3", {
local res = orientation(pos, {"techage:ta3_distiller2"})
return res
end,
tubelib2_on_update2 = tubelib2_on_update2,
after_dig_node = after_dig_node,
paramtype = "light",
@ -185,15 +164,10 @@ minetest.register_node("techage:ta3_distiller3", {
groups = {cracky=2},
is_ground_content = false,
sounds = default.node_sound_metal_defaults(),
networks = {
pipe2 = {
sides = {B=1}, -- Pipe connection sides
ntype = "pump",
},
},
})
liquid.register_nodes({"techage:ta3_distiller3"}, Pipe, "pump", {"B"}, {})
minetest.register_node("techage:ta3_distiller4", {
description = S("TA3 Distillation Tower 4"),
tiles = {"techage_distiller4.png"},
@ -213,8 +187,6 @@ minetest.register_node("techage:ta3_distiller4", {
after_place_node(pos, placer)
return res
end,
tubelib2_on_update2 = tubelib2_on_update2,
after_dig_node = after_dig_node,
paramtype = "light",
@ -223,40 +195,28 @@ minetest.register_node("techage:ta3_distiller4", {
groups = {cracky=2},
is_ground_content = false,
sounds = default.node_sound_metal_defaults(),
networks = {
pipe2 = {
sides = {U=1}, -- Pipe connection sides
ntype = "pump",
},
},
})
liquid.register_nodes({"techage:ta3_distiller4"}, Pipe, "pump", {"U"}, {})
Pipe:add_secondary_node_names({
"techage:ta3_distiller_base", "techage:ta3_distiller1",
"techage:ta3_distiller3", "techage:ta3_distiller4",
})
local Liquids = {
[-1] = "techage:bitumen",
[2] = "techage:fueloil",
[4] = "techage:naphtha",
[6] = "techage:gasoline",
[7] = "techage:gas",
}
local Liquids = {"techage:bitumen", "techage:fueloil", "techage:naphtha", "techage:gasoline", "techage:gas"}
local YPos = {-1, 2, 4, 6, 7}
techage.register_node({"techage:ta3_distiller1"}, {
on_transfer = function(pos, in_dir, topic, payload)
if topic == "put" then
local leftover = 0
local outdir = M(pos):get_int("outdir")
for _,y in ipairs({-1, 2, 4, 6, 7}) do
local pos2 = {x = pos.x, y = pos.y + y, z = pos.z}
if y == 7 then
outdir = 6
end
leftover = leftover + liquid.put(pos2, outdir, Liquids[y], 1)
local nvm = techage.get_nvm(pos)
nvm.idx = nvm.idx or 1
local outdir
if nvm.idx == 5 then
outdir = 6 -- up
else
outdir = M(pos):get_int("outdir")
end
local pos2 = {x = pos.x, y = pos.y + YPos[nvm.idx], z = pos.z}
local leftover = liquid.put(pos2, Pipe, outdir, Liquids[nvm.idx], 1)
if leftover == 0 then
nvm.idx = (nvm.idx % 5) + 1
end
return leftover
end

View File

@ -238,7 +238,7 @@ local tubing = {
local nvm = techage.get_nvm(pos)
if not nvm.assemble_locked then
local meta = minetest.get_meta(pos)
if meta:get_int("push_dir") == in_dir or in_dir == 5 then
if meta:get_int("push_dir") == in_dir then
local inv = M(pos):get_inventory()
CRD(pos).State:start_if_standby(pos)
return techage.put_items(inv, "src", stack)
@ -299,6 +299,7 @@ local _, node_name_ta3, _ =
sounds = default.node_sound_wood_defaults(),
num_items = {0,1,1,1},
power_consumption = {0,10,16,24},
tube_sides = {L=1, R=1},
},
{false, false, true, false}) -- TA3 only

View File

@ -23,7 +23,7 @@ local OIL_MAX = 20000
local DEPTH_MIN = 16
local DEPTH_MAX = 25*16
local DEPTH_STEP = 16
local YPOS_MAX = -6*16 -- oil can found below this level
local YPOS_MAX = -6*16 -- oil can't found below this level
local OIL_BUBBLE_SIZE = 4096
local seed = tonumber(minetest.settings:get("techage_oil_exploration_seed")) or 1234 -- confidental!

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -18,7 +18,7 @@ local M = minetest.get_meta
local P = minetest.string_to_pos
local S = techage.S
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local liquid = networks.liquid
-- Consumer Related Data
local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end
@ -103,7 +103,7 @@ end
local function pumping(pos, crd, meta, nvm)
if has_oil(pos, meta) then
local leftover = liquid.put(pos, 6, "techage:oil_source", 1)
local leftover = liquid.put(pos, Pipe, 6, "techage:oil_source", 1)
if leftover and leftover > 0 then
crd.State:blocked(pos, nvm)
stop_sound(pos)
@ -211,12 +211,6 @@ local _, node_name_ta3, _ =
end
Pipe:after_place_node(pos)
end,
networks = {
pipe2 = {
sides = {U = 1}, -- Pipe connection side
ntype = "pump",
},
},
power_sides = {F=1, B=1, L=1, R=1, D=1},
on_rightclick = on_rightclick,
on_receive_fields = on_receive_fields,
@ -244,5 +238,5 @@ minetest.register_craft({
},
})
Pipe:add_secondary_node_names({"techage:ta3_pumpjack_pas", "techage:ta3_pumpjack_act"})
liquid.register_nodes({"techage:ta3_pumpjack_pas", "techage:ta3_pumpjack_act"}, Pipe, "pump", {"U"}, {})

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -16,15 +16,14 @@ local S2P = minetest.string_to_pos
local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local Flip = networks.Flip
local Pipe = techage.LiquidPipe
local networks = techage.networks
local liquid = techage.liquid
local Flip = techage.networks.Flip
local Cable = techage.ElectricCable
local power = techage.power
local liquid = networks.liquid
local power = networks.power
local CYCLE_TIME = 16
local CAPA = 12
local CYCLE_TIME = 2
local WAITING_CYCLES = 5 -- in case BLOCKED
local PWR_NEEDED = 14
local function play_sound(pos)
@ -51,90 +50,98 @@ end
local function swap_node(pos, on)
local nvm = techage.get_nvm(pos)
if on then
local node = techage.get_node_lvm(pos)
local node = techage.get_node_lvm(pos)
if on and node.name == "techage:ta3_reboiler" then
node.name = "techage:ta3_reboiler_on"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):start(CYCLE_TIME)
play_sound(pos)
elseif not on and nvm.running then
local node = techage.get_node_lvm(pos)
elseif not on and node.name == "techage:ta3_reboiler_on" then
node.name = "techage:ta3_reboiler"
minetest.swap_node(pos, node)
minetest.get_node_timer(pos):stop()
nvm.running = false
power.consumer_stop(pos, Cable)
stop_sound(pos)
end
end
local function on_power(pos)
swap_node(pos, true)
end
local function on_nopower(pos)
swap_node(pos, false)
end
local function is_running(pos, nvm)
return nvm.running
end
local function pump_cmnd(pos, cmnd, payload)
return techage.transfer(
local function pump_cmnd(pos)
local leftover = techage.transfer(
pos,
"R", -- outdir
cmnd, -- topic
payload, -- payload
"put", -- topic
nil, -- payload
Pipe, -- Pipe
{"techage:ta3_distiller1"})
-- number of processed oil items
return 1 - (tonumber(leftover) or 1)
end
local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos)
nvm.liquid = nvm.liquid or {}
nvm.liquid.amount = nvm.liquid.amount or 0
if not nvm.error or nvm.error == 0 then
power.consumer_alive(pos, Cable, CYCLE_TIME)
local function new_state(pos, nvm, state)
if nvm.state ~= state then
nvm.state = state
M(pos):set_string("infotext", S("TA3 Oil Reboiler") .. ": " .. techage.StateStrings[state])
swap_node(pos, state == techage.RUNNING)
end
if nvm.liquid.amount >= 5 and nvm.liquid.name == "techage:oil_source" then
nvm.liquid.amount = nvm.liquid.amount - 5
local leftover = pump_cmnd(pos, "put")
if (tonumber(leftover) or 1) > 0 then
nvm.liquid.amount = nvm.liquid.amount + 5
nvm.error = 2 -- = 2 pump cycles
M(pos):set_string("infotext", S("TA3 Oil Reboiler: blocked"))
swap_node(pos, false)
return false
end
return true
end
swap_node(pos, false)
return false
end
end
local function start_node(pos)
local function on_timer(pos)
local nvm = techage.get_nvm(pos)
if nvm.running then return end
nvm.oil_amount = nvm.oil_amount or 0
nvm.liquid = nvm.liquid or {}
nvm.liquid.amount = nvm.liquid.amount or 0
if nvm.liquid.amount >= 5 and nvm.liquid.name == "techage:oil_source" then
if power.power_available(pos, Cable) then
if node_timer(pos, CYCLE_TIME) then
nvm.running = true
power.consumer_start(pos, Cable, CYCLE_TIME)
minetest.get_node_timer(pos):start(CYCLE_TIME)
-- Power handling
if nvm.state == techage.STOPPED then
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed == PWR_NEEDED then
new_state(pos, nvm, techage.RUNNING)
return true
end
elseif nvm.state == techage.RUNNING then
local consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED)
if consumed < PWR_NEEDED then
local nvm = techage.get_nvm(pos)
new_state(pos, nvm, techage.STOPPED)
return true
end
elseif nvm.state == techage.BLOCKED or nvm.state == techage.STANDBY then
if not power.power_available(pos, Cable) then
local nvm = techage.get_nvm(pos)
new_state(pos, nvm, techage.STOPPED)
return true
end
end
-- Oil handling
if nvm.state == techage.RUNNING then
if nvm.oil_amount >= 1 then
local processed = pump_cmnd(pos)
nvm.oil_amount = nvm.oil_amount - processed
nvm.waiting_cycles = WAITING_CYCLES
if processed == 0 then
new_state(pos, nvm, techage.BLOCKED)
else
new_state(pos, nvm, techage.RUNNING)
end
else
nvm.waiting_cycles = (nvm.waiting_cycles or 0) - 1
if nvm.waiting_cycles <= 0 then
new_state(pos, nvm, techage.STANDBY)
end
end
elseif nvm.state == techage.BLOCKED then
nvm.waiting_cycles = nvm.waiting_cycles - 1
if nvm.waiting_cycles <= 0 then
new_state(pos, nvm, techage.RUNNING)
end
else
-- STANDBY: 'put' will trigger the state change
end
return true
end
local function after_place_node(pos)
local nvm = techage.get_nvm(pos)
new_state(pos, nvm, techage.STOPPED)
Pipe:after_place_node(pos)
Cable:after_place_node(pos)
Cable.after_place_node(pos)
end
local function after_dig_node(pos, oldnode)
@ -143,51 +150,13 @@ local function after_dig_node(pos, oldnode)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
if tlib2.tube_type == "pipe2" then
liquid.update_network(pos, outdir, tlib2)
else
power.update_network(pos, outdir, tlib2)
end
local function on_rightclick(pos, node, clicker)
local nvm = techage.get_nvm(pos)
nvm.oil_amount = 0
new_state(pos, nvm, techage.STOPPED)
minetest.get_node_timer(pos):start(CYCLE_TIME)
end
local liquid_def = {
capa = CAPA,
peek = liquid.srv_peek,
put = function(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
if nvm.error and nvm.error > 0 then
nvm.error = nvm.error - 1
if nvm.error <= 0 then
M(pos):set_string("infotext", S("TA3 Oil Reboiler"))
start_node(pos)
return liquid.srv_put(pos, indir, name, amount)
else
return amount
end
else
start_node(pos)
return liquid.srv_put(pos, indir, name, amount)
end
end,
take = liquid.srv_take,
}
local net_def = {
pipe2 = {
sides = {L = true, R = true}, -- Pipe connection sides
ntype = "tank",
},
ele1 = {
sides = techage.networks.AllSides, -- Cable connection sides
ntype = "con1",
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED,
is_running = is_running,
},
}
minetest.register_node("techage:ta3_reboiler", {
description = S("TA3 Oil Reboiler"),
tiles = {
@ -200,26 +169,10 @@ minetest.register_node("techage:ta3_reboiler", {
"techage_filling_ta3.png^techage_appl_reboiler.png^techage_frame_ta3.png",
},
after_place_node = function(pos, placer)
local nvm = techage.get_nvm(pos)
nvm.liquid = {}
local meta = M(pos)
meta:set_string("infotext", S("TA3 Oil Reboiler"))
meta:set_int("outdir", networks.side_to_outdir(pos, "R"))
local number = techage.add_node(pos, "techage:ta3_reboiler")
meta:set_string("node_number", number)
meta:set_string("owner", placer:get_player_name())
Pipe:after_place_node(pos)
power.after_place_node(pos)
end,
tubelib2_on_update2 = tubelib2_on_update2,
on_timer = node_timer,
on_timer = on_timer,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
after_dig_node = after_dig_node,
liquid = liquid_def,
networks = net_def,
on_rightclick = on_rightclick,
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
@ -258,10 +211,8 @@ minetest.register_node("techage:ta3_reboiler_on", {
},
},
tubelib2_on_update2 = tubelib2_on_update2,
on_timer = node_timer,
liquid = liquid_def,
networks = net_def,
on_timer = on_timer,
on_rightclick = on_rightclick,
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
@ -271,25 +222,43 @@ minetest.register_node("techage:ta3_reboiler_on", {
sounds = default.node_sound_metal_defaults(),
})
Pipe:add_secondary_node_names({"techage:ta3_reboiler", "techage:ta3_reboiler_on"})
Cable:add_secondary_node_names({"techage:ta3_reboiler", "techage:ta3_reboiler_on"})
local liquid_def = {
peek = function(pos)
local nvm = techage.get_nvm(pos)
return liquid.srv_peek(nvm)
end,
put = function(pos, indir, name, amount)
local nvm = techage.get_nvm(pos)
nvm.oil_amount = nvm.oil_amount or 0
if nvm.state == techage.STANDBY or nvm.state == techage.RUNNING then
if name == "techage:oil_source" and amount > 0 then
if nvm.state == techage.STANDBY then
new_state(pos, nvm, techage.RUNNING)
end
-- Take one oil item every 2 cycles
-- Hint: We have to take two items, because the pump will pause for 4 cycles,
-- if nothing is taken.
nvm.take = nvm.take ~= true
if nvm.take and nvm.oil_amount < 5 then
nvm.oil_amount = nvm.oil_amount + 2
return amount - 2
end
end
end
return amount
end
}
liquid.register_nodes({"techage:ta3_reboiler", "techage:ta3_reboiler_on"}, Pipe, "tank", {"L", "R"}, liquid_def)
power.register_nodes({"techage:ta3_reboiler", "techage:ta3_reboiler_on"}, Cable, "con")
techage.register_node({"techage:ta3_reboiler", "techage:ta3_reboiler_on"}, {
on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "on" then
start_node(pos)
return true
elseif topic == "off" then
swap_node(pos, false)
return true
elseif topic == "state" then
if nvm.error and nvm.error > 0 then
return "blocked"
elseif nvm.running then
return "running"
end
return "stopped"
if topic == "state" then
nvm.state = nvm.state or techage.STOPPED
return techage.StateStrings[nvm.state]
else
return "unsupported"
end
@ -298,6 +267,7 @@ techage.register_node({"techage:ta3_reboiler", "techage:ta3_reboiler_on"}, {
if node.name == "techage:ta3_reboiler_on" then
play_sound(pos)
end
minetest.get_node_timer(pos):start(CYCLE_TIME)
end,
})

View File

@ -1,162 +0,0 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
Power Distribution
]]--
local N = function(pos) return techage.get_node_lvm(pos).name end
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local net_def = techage.networks.net_def
local STOPPED = techage.power.STOPPED
local NOPOWER = techage.power.NOPOWER
local RUNNING = techage.power.RUNNING
local function start_consumer(tbl, tlib_type)
for _,v in pairs(tbl or {}) do
local nvm = techage.get_nvm(v.pos)
local def = nvm[tlib_type] -- power related network data
if def and def["cstate"] == NOPOWER and (def["calive"] or 0) > 0 then
local ndef = net_def(v.pos, tlib_type)
def["cstate"] = RUNNING
def["taken"] = v.nominal or def.curr_power or 0
if ndef.on_power then
ndef.on_power(v.pos, tlib_type)
end
end
end
end
local function stop_consumer(tbl, tlib_type)
for _,v in pairs(tbl or {}) do
local nvm = techage.get_nvm(v.pos)
local def = nvm[tlib_type] -- power related network data
local ndef = net_def(v.pos, tlib_type)
if (def and def["cstate"] == RUNNING) or (ndef.is_running and ndef.is_running(v.pos, nvm)) then
def["cstate"] = NOPOWER
def["taken"] = 0
if ndef.on_nopower then
ndef.on_nopower(v.pos, tlib_type)
end
end
end
end
local function get_generator_sum(tbl, tlib_type, cycle_time)
local sum = 0
for _,v in ipairs(tbl or {}) do
local nvm = techage.get_nvm(v.pos)
local def = nvm[tlib_type] -- power related network data
if def and def["gstate"] ~= STOPPED then
def["galive"] = (def["galive"] or 1) - cycle_time/2
if def["galive"] >= 0 then
sum = sum + (def.curr_power or v.nominal)
end
end
end
return sum
end
local function get_consumer_sum(tbl, tlib_type, cycle_time)
local sum = 0
for _,v in ipairs(tbl or {}) do
local nvm = techage.get_nvm(v.pos)
local def = nvm[tlib_type] -- power related network data
if def and def["cstate"] ~= STOPPED then
def["calive"] = (def["calive"] or 1) - cycle_time/2
if def["calive"] >= 0 then
sum = sum + (v.nominal or def.curr_power or 0)
end
end
--print(N(v.pos), P2S(v.pos), def["cstate"], def["calive"], sum)
end
return sum
end
local function set_given(pos, given, tlib_type)
local nvm = techage.get_nvm(pos)
local def = nvm[tlib_type] -- power related network data
if (def and def["galive"] or 0) > 0 then
if def.curr_power and def.curr_power < given then
def["given"] = def.curr_power
else
def["given"] = given
end
return def["given"]
end
return 0
end
local function set_taken(pos, taken, tlib_type)
local nvm = techage.get_nvm(pos)
local def = nvm[tlib_type] -- power related network data
if (def and def["calive"] or 0) > 0 then
def["taken"] = taken
def["cstate"] = RUNNING
return taken
end
return 0
end
local function set_given_values(tbl, needed, tlib_type)
for _,v in ipairs(tbl or {}) do
local real = math.max(math.min(needed, v.nominal), 0)
real = set_given(v.pos, real, tlib_type)
needed = needed - real
end
return needed
end
local function set_taken_values(tbl, taken, tlib_type)
for _,v in pairs(tbl or {}) do
local real = math.max(math.min(taken, v.nominal), 0)
real = set_taken(v.pos, real, tlib_type)
taken = taken - real
end
return taken
end
function techage.power.power_distribution(network, tlib_type, netID, cycle_time)
-- calc maximum power values
network.available1 = get_generator_sum(network.gen1, tlib_type, cycle_time)
network.available2 = get_generator_sum(network.gen2, tlib_type, cycle_time)
network.needed1 = get_consumer_sum(network.con1, tlib_type, cycle_time)
network.needed2 = get_consumer_sum(network.con2, tlib_type, cycle_time)
--print(string.format("%X", netID), network.available1, network.available2, network.needed1, network.needed2)
-- store results
network.on = network.available1 + network.available2 >= network.needed1
if network.on then
network.ticker = (network.ticker or 0) + 1
set_given_values(network.gen1, network.needed1 + network.needed2, tlib_type)
set_given_values(network.gen2, network.needed1 - network.available1, tlib_type)
start_consumer(network.con1, tlib_type)
set_taken_values(network.con2, network.available1 - network.needed1, tlib_type)
else
set_given_values(network.gen1, 0, tlib_type)
set_given_values(network.gen2, 0, tlib_type)
stop_consumer(network.con1, tlib_type)
set_taken_values(network.con2, 0, tlib_type)
end
end
-- determine the maxiumum needed power of all con1 consumers
function techage.power.get_con1_sum(network, tlib_type)
local sum = 0
for _,v in ipairs(network.con1 or {}) do
local nvm = techage.get_nvm(v.pos)
local def = nvm[tlib_type] -- power related network data
if def and def["cstate"] ~= STOPPED then
sum = sum + (v.nominal or def.curr_power or 0)
end
end
return sum
end

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -17,13 +17,15 @@ local P = minetest.string_to_pos
local M = minetest.get_meta
local S = techage.S
local power = networks.power
local Axle = tubelib2.Tube:new({
dirs_to_check = {1,2,3,4,5,6},
max_tube_length = 8,
max_tube_length = 10,
show_infotext = false,
tube_type = "axle",
primary_node_names = {"techage:axle", "techage:axle_on"},
secondary_node_names = {"techage:flywheel", "techage:flywheel_on", "techage:gearbox", "techage:gearbox_on"},
secondary_node_names = {},
after_place_tube = function(pos, param2, tube_type, num_tubes, state)
if state == "on" then
minetest.swap_node(pos, {name = "techage:axle_on", param2 = param2})
@ -33,6 +35,10 @@ local Axle = tubelib2.Tube:new({
end,
})
-- Use global callback instead of node related functions
Axle:register_on_tube_update2(function(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2, node)
end)
minetest.register_node("techage:axle", {
description = S("TA2 Drive Axle"),

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -18,7 +18,7 @@ local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local power = techage.power
local power = networks.power
local ELE1_MAX_CABLE_LENGHT = 1000
@ -29,56 +29,32 @@ local Cable = tubelib2.Tube:new({
tube_type = "ele1",
primary_node_names = {"techage:electric_cableS", "techage:electric_cableA",
"techage:power_line", "techage:power_lineS", "techage:power_lineA",
"techage:power_pole2", "techage:powerswitch_box"},
"techage:power_pole2", "techage:powerswitch_box", "techage:powerswitch_box_on"},
secondary_node_names = {},
after_place_tube = function(pos, param2, tube_type, num_tubes)
-- Handle "power line" nodes
local name = minetest.get_node(pos).name
if name == "techage:power_pole2" then
M(pos):set_int("tl2_param2", param2)
return
elseif name == "techage:powerswitch_box" then
minetest.swap_node(pos, {name = "techage:powerswitch_box", param2 = param2 % 32})
M(pos):set_int("tl2_param2", param2)
return
if name == "techage:powerswitch_box" or name == "techage:powerswitch_box_on" or name == "techage:powerswitch_box_off" then
minetest.swap_node(pos, {name = name, param2 = param2 % 32})
elseif name == "techage:power_line" or name == "techage:power_lineS" or name == "techage:power_lineA" then
minetest.swap_node(pos, {name = "techage:power_line"..tube_type, param2 = param2 % 32})
M(pos):set_int("tl2_param2", param2)
return
end
-- Don't replace "hidden" cable
if M(pos):get_string("techage_hidden_nodename") == "" then
elseif name == "techage:power_pole2" then
-- nothing
elseif not networks.hidden_name(pos) then
minetest.swap_node(pos, {name = "techage:electric_cable"..tube_type, param2 = param2 % 32})
end
M(pos):set_int("tl2_param2", param2)
print("param2", name, param2)
M(pos):set_int("netw_param2", param2)
end,
})
-- Enable hidden cables
networks.use_metadata(Cable)
networks.register_hidden_message("Use the trowel tool to remove the node.")
-- Overridden method of tubelib2!
function Cable:get_primary_node_param2(pos, dir)
return techage.get_primary_node_param2(pos, dir)
end
function Cable:is_primary_node(pos, dir)
return techage.is_primary_node(pos, dir)
end
function Cable:get_secondary_node(pos, dir)
local npos = vector.add(pos, tubelib2.Dir6dToVector[dir or 0])
local node = self:get_node_lvm(npos)
if self.secondary_node_names[node.name] or
self.secondary_node_names[M(npos):get_string("techage_hidden_nodename")] then
return node, npos, true
end
end
function Cable:is_secondary_node(pos, dir)
local npos = vector.add(pos, tubelib2.Dir6dToVector[dir or 0])
local node = self:get_node_lvm(npos)
return self.secondary_node_names[node.name] or
self.secondary_node_names[M(npos):get_string("techage_hidden_nodename")]
end
-- Use global callback instead of node related functions
Cable:register_on_tube_update2(function(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2, node)
end)
minetest.register_node("techage:electric_cableS", {
description = S("TA Electric Cable"),
@ -101,10 +77,7 @@ minetest.register_node("techage:electric_cableS", {
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
if oldmetadata and oldmetadata.fields and oldmetadata.fields.tl2_param2 then
oldnode.param2 = oldmetadata.fields.tl2_param2
Cable:after_dig_tube(pos, oldnode)
end
Cable:after_dig_tube(pos, oldnode, oldmetadata)
end,
paramtype2 = "facedir", -- important!
@ -137,10 +110,7 @@ minetest.register_node("techage:electric_cableA", {
},
after_dig_node = function(pos, oldnode, oldmetadata, digger)
if oldmetadata and oldmetadata.fields and oldmetadata.fields.tl2_param2 then
oldnode.param2 = oldmetadata.fields.tl2_param2
Cable:after_dig_tube(pos, oldnode)
end
Cable:after_dig_tube(pos, oldnode, oldmetadata)
end,
paramtype2 = "facedir", -- important!
@ -163,11 +133,6 @@ minetest.register_node("techage:electric_cableA", {
drop = "techage:electric_cableS",
})
-- only needed for hidden nodes, cause they don't have a tubelib2_on_update2 callback
Cable:register_on_tube_update(function(node, pos, out_dir, peer_pos, peer_in_dir)
power.update_network(pos, nil, Cable)
end)
minetest.register_craft({
output = "techage:electric_cableS 6",
recipe = {

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -15,57 +15,280 @@
--local P2S = minetest.pos_to_string
--local M = minetest.get_meta
--local N = function(pos) return minetest.get_node(pos).name end
--local S = techage.S
local in_range = techage.in_range
local S = techage.S
function techage.power.percent(max_val, curr_val)
return math.min(math.ceil(((curr_val or 0) * 100) / (max_val or 1.0)), 100)
local CYCLE_TIME = 2
local CYCLES_PER_DAY = 20 * 60 / CYCLE_TIME
local in_range = techage.in_range
local power = networks.power
techage.power = {}
-------------------------------------------------------------------------------
-- Helper function
-------------------------------------------------------------------------------
local function round(val)
if val > 100 then
return math.floor(val + 0.5)
elseif val > 10 then
return math.floor((val * 10) + 0.5) / 10
else
return math.floor((val * 100) + 0.5) / 100
end
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
local function calc_percent(max_val, curr_val)
return math.min(((curr_val or 0) * 100) / (max_val or 1.0), 100)
end
-------------------------------------------------------------------------------
-- Local bar functions
-------------------------------------------------------------------------------
-- charging > 0 ==> charging
-- charging < 0 ==> uncharging
-- charging = 0 ==> off
-- percent: 0..100
local function charging_bar(charging, percent)
if charging > 0 then
return "techage_form_level_off.png^[lowpart:"..percent..":techage_form_level_charge.png"
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"
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)
if (current_power or 0) == 0 then
return "techage_form_level_bg.png"
local function power_bar(current_power, max_power)
local percent, ypos
current_power = current_power or 0
if current_power == 0 then
percent = 0
ypos = 2.8
else
percent = calc_percent(max_power, current_power)
-- 0.4 to 2.8 = 2.4
local offs = 2.4 - (current_power / max_power) * 2.4
ypos = 0.4 + in_range(offs, 0.4, 2.4)
end
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"
current_power = round(current_power)
max_power = round(max_power)
percent = (percent + 5) / 1.1 -- texture correction
return "label[0.7,0.4;" .. max_power .. " ku]" ..
"image[0,0.5;1,3;" ..
"techage_form_level_bg.png^[lowpart:" .. percent ..
":techage_form_level_fg.png]" ..
"label[0.7," .. ypos .. ";" .. current_power .. " ku]"
end
function techage.power.formspec_label_bar(pos, x, y, label, max_power, current_power, unit)
local function storage_bar(current_power, max_power)
local percent, ypos
max_power = (max_power or 1) / CYCLES_PER_DAY
current_power = (current_power or 0) / CYCLES_PER_DAY
if current_power == 0 then
percent = 0
ypos = 2.8
else
percent = calc_percent(max_power, current_power)
-- 0.4 to 2.8 = 2.4
local offs = 2.4 - (current_power / max_power) * 2.4
ypos = 0.4 + in_range(offs, 0.4, 2.4)
end
current_power = round(current_power)
max_power = round(max_power)
local percent2 = (percent + 5) / 1.1 -- texture correction
return "label[0.7,0.4;" .. max_power .. " kud]" ..
"image[0,0.5;1,3;"..
"techage_form_level_bg.png^[lowpart:" .. percent2 ..
":techage_form_level_fg.png]" ..
"label[0.7," .. ypos .. ";" .. round(percent) .. " %]"
end
-------------------------------------------------------------------------------
-- API bar functions
-------------------------------------------------------------------------------
function techage.formspec_power_bar(pos, x, y, label, current_power, max_power)
return "container["..x..","..y.."]"..
"box[0,0;2.3,3.3;#395c74]"..
"label[0.2,0;"..label.."]"..
power_bar(current_power, max_power)..
"container_end[]"
end
function techage.formspec_charging_bar(pos, x, y, label, data)
local charging = 0
local percent = 50
local ypos = 1.6
if data then
charging = data.provided - data.consumed
if charging > 0 then
percent = 50 + (charging / data.available * 50)
ypos = 1.6 - (charging / data.available * 1.2)
elseif charging < 0 then
percent = 50 + (charging / data.consumed * 50)
ypos = 1.6 - (charging / data.consumed * 1.2)
end
end
ypos = in_range(ypos, 0.4, 2.8)
return "container[".. x .. "," .. y .. "]" ..
"box[0,0;2.3,3.3;#395c74]" ..
"label[0.2,0;" .. label .. "]" ..
"image[0,0.5;1,3;" .. charging_bar(charging, percent) .. "]" ..
"label[0.75," .. ypos .. ";" .. round(charging) .. " ku]" ..
"container_end[]"
end
function techage.formspec_storage_bar(pos, x, y, label, curr_load, max_load)
curr_load = curr_load or 0
return "container[" .. x .. "," .. y .. "]" ..
"box[0,0;2.3,3.3;#395c74]" ..
"label[0.2,0;" .. label .. "]" ..
storage_bar(curr_load, max_load) ..
"container_end[]"
end
function techage.formspec_meter(pos, x, y, label, value, unit)
return "container[" .. x .. "," .. y .. "]" ..
"box[0,0;2.3,1.2;#395c74]" ..
"label[0.2,0.0;" .. label .. ":]" ..
"label[0.2,0.5;" .. round(value) .. " " .. unit .. "]" ..
"container_end[]"
end
-------------------------------------------------------------------------------
-- API formspec functions
-------------------------------------------------------------------------------
function techage.storage_formspec(self, pos, nvm, label, netw_data, curr_load, max_load)
return "size[6.3,4]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"box[0,-0.1;6.1,0.5;#c6e8ff]" ..
"label[0.2,-0.1;" .. minetest.colorize( "#000000", label) .. "]" ..
techage.formspec_charging_bar(pos, 0.0, 0.8, S("Charging"), netw_data) ..
techage.formspec_storage_bar (pos, 3.8, 0.8, S("Storage"), curr_load, max_load) ..
"image_button[2.7,2;1,1;" .. self:get_state_button_image(nvm) .. ";state_button;]" ..
"tooltip[2.7,2;1,1;" .. self:get_state_tooltip(nvm) .. "]"
end
function techage.generator_formspec(self, pos, nvm, label, provided, max_available, ta2)
local tooltip = ""
if not ta2 then
tooltip = techage.wrench_tooltip(4.4, -0.1)
end
return "size[5,4]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"box[0,-0.1;4.8,0.5;#c6e8ff]" ..
"label[0.2,-0.1;" .. minetest.colorize( "#000000", label) .. "]" ..
tooltip..
techage.formspec_power_bar(pos, 0, 0.8, S("Power"), provided, max_available) ..
"image_button[3.2,2.0;1,1;" .. self:get_state_button_image(nvm) .. ";state_button;]" ..
"tooltip[3.2,2.0;1,1;" .. self:get_state_tooltip(nvm) .. "]"
end
function techage.generator_settings(tier, available)
if tier == "ta3" then
return {
{
type = "const",
name = "available",
label = S("Maximum output [ku]"),
tooltip = S("The maximum power the generator can provide"),
value = available,
},
{
type = "output",
name = "provided",
label = S("Current output [ku]"),
tooltip = S("The current power the generator provides"),
},
{
type = "dropdown",
choices = "0% - 20%,20% - 40%,40% - 60%,60% - 80%,80% - 100%,90% - 100%",
name = "termpoint",
label = S("Charge termination"),
tooltip = S("Range in which the generator reduces its power"),
default = "80% - 100%",
},
}
else
return {
{
type = "const",
name = "available",
label = S("Maximum output [ku]"),
tooltip = S("The maximum power the generator can provide"),
value = available,
},
{
type = "output",
name = "provided",
label = S("Current output [ku]"),
tooltip = S("The current power the generator provides"),
},
{
type = "dropdown",
choices = "0% - 20%,20% - 40%,40% - 60%,60% - 80%,80% - 100%,90% - 100%",
name = "termpoint",
label = S("Charge termination"),
tooltip = S("Range in which the generator reduces its power"),
default = "80% - 100%",
},
}
end
end
function techage.evaluate_charge_termination(nvm, meta)
local termpoint = meta:get_string("termpoint")
if termpoint == "0% - 20%" then
meta:set_string("termpoint1", 0.0)
meta:set_string("termpoint2", 0.2)
elseif termpoint == "20% - 40%" then
meta:set_string("termpoint1", 0.2)
meta:set_string("termpoint2", 0.4)
elseif termpoint == "40% - 60%" then
meta:set_string("termpoint1", 0.4)
meta:set_string("termpoint2", 0.6)
elseif termpoint == "60% - 80%" then
meta:set_string("termpoint1", 0.6)
meta:set_string("termpoint2", 0.8)
elseif termpoint == "80% - 100%" then
meta:set_string("termpoint1", 0.8)
meta:set_string("termpoint2", 1.0)
elseif termpoint == "90% - 100%" then
meta:set_string("termpoint1", 0.9)
meta:set_string("termpoint2", 1.0)
else
meta:set_string("termpoint", "80% - 100%")
meta:set_string("termpoint1", 0.8)
meta:set_string("termpoint2", 1.0)
end
end
techage.power.percent = calc_percent
techage.CYCLES_PER_DAY = CYCLES_PER_DAY
techage.round = round
-------------------------------------------------------------------------------
-- Still used legacy functions
-------------------------------------------------------------------------------
function techage.formspec_label_bar(pos, x, y, label, max_power, current_power, unit)
local percent, ypos
max_power = max_power or 1
unit = unit or "ku"
if current_power == 0 then
-- check if power network is overloaded
if techage.power.network_overloaded(pos, techage.ElectricCable) then
return "container["..x..","..y.."]"..
"box[0,0;2.3,3.3;#395c74]"..
"label[0.2,0;"..label.."]"..
"label[0.7,0.4;"..max_power.." "..unit.."]"..
"image[0,0.5;1,3;techage_form_level_red_fg.png]"..
"container_end[]"
end
end
current_power = current_power or 0
if current_power == 0 then
percent = 0
ypos = 2.8

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -18,15 +18,14 @@ local M = minetest.get_meta
local S = techage.S
local PWR_NEEDED = 1
local CYCLE_TIME = 4
local CYCLE_TIME = 2
local Axle = techage.Axle
local power = techage.power
local networks = techage.networks
local power = networks.power
-- Axles texture animation
local function switch_axles(pos, on)
for _,outdir in ipairs(networks.get_node_connections(pos, "axle")) do
for _,outdir in ipairs(networks.get_outdirs(pos, Axle)) do
Axle:switch_tube_line(pos, outdir, on and "on" or "off")
end
end
@ -40,63 +39,56 @@ local function swap_node(pos, name)
minetest.swap_node(pos, node)
end
local function on_power(pos)
swap_node(pos, "techage:gearbox_on")
switch_axles(pos, true)
local function node_timer_on(pos, elapsed)
local consumed = power.consume_power(pos, Axle, 0, PWR_NEEDED)
if consumed == 0 then
swap_node(pos, "techage:gearbox")
switch_axles(pos, false)
end
return true
end
local function on_nopower(pos)
swap_node(pos, "techage:gearbox")
switch_axles(pos, false)
end
local function node_timer(pos, elapsed)
power.consumer_alive(pos, Axle, CYCLE_TIME)
local function node_timer_off(pos, elapsed)
if power.power_available(pos, Axle, 0) then
swap_node(pos, "techage:gearbox_on")
switch_axles(pos, true)
end
return true
end
-- to be able to restart the node after server crashes
local function techage_on_repair(pos)
minetest.get_node_timer(pos):start(CYCLE_TIME)
power.consumer_start(pos, Axle, CYCLE_TIME)
end
local function after_place_node(pos)
Axle:after_place_node(pos)
minetest.get_node_timer(pos):start(CYCLE_TIME)
power.consumer_start(pos, Axle, CYCLE_TIME)
end
local function after_dig_node(pos, oldnode)
Axle:after_dig_node(pos)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, nil, tlib2)
local function tubelib2_on_update2_on(pos, outdir, tlib2, node)
power.update_network(pos, 0, tlib2, node)
switch_axles(pos, true)
end
local net_def = {
axle = {
sides = techage.networks.AllSides, -- Cable connection sides
ntype = {"con1", "junc"},
on_power = on_power,
on_nopower = on_nopower,
nominal = PWR_NEEDED,
},
}
local function tubelib2_on_update2_off(pos, outdir, tlib2, node)
power.update_network(pos, 0, tlib2, node)
switch_axles(pos, false)
end
minetest.register_node("techage:gearbox", {
description = S("TA2 Gearbox"),
tiles = {"techage_filling_ta2.png^techage_axle_gearbox.png^techage_frame_ta2.png"},
on_timer = node_timer,
on_timer = node_timer_off,
techage_on_repair = techage_on_repair,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
tubelib2_on_update2 = tubelib2_on_update2_off,
paramtype = "light",
light_source = 0,
paramtype2 = "facedir",
@ -122,13 +114,11 @@ minetest.register_node("techage:gearbox_on", {
},
},
on_timer = node_timer,
on_timer = node_timer_on,
techage_on_repair = techage_on_repair,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
tubelib2_on_update2 = tubelib2_on_update2_on,
paramtype2 = "facedir",
groups = {not_in_creative_inventory=1},
diggable = false,
@ -138,8 +128,14 @@ minetest.register_node("techage:gearbox_on", {
sounds = default.node_sound_wood_defaults(),
})
Axle:add_secondary_node_names({"techage:gearbox", "techage:gearbox_on"})
power.register_nodes({"techage:gearbox", "techage:gearbox_on"}, Axle, "junc")
techage.register_node({"techage:gearbox", "techage:gearbox_on"}, {
on_node_load = function(pos, node)
minetest.get_node_timer(pos):start(CYCLE_TIME)
end,
})
minetest.register_craft({
output = "techage:gearbox 2",
recipe = {

View File

@ -1,130 +0,0 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
Junction for power distribution
]]--
-- 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
local function bit(p)
return 2 ^ (p - 1) -- 1-based indexing
end
-- Typical call: if hasbit(x, bit(3)) then ...
local function hasbit(x, p)
return x % (p + p) >= p
end
local function setbit(x, p)
return hasbit(x, p) and x or x + p
end
local function get_node_box(val, size, boxes)
local fixed = {{-size, -size, -size, size, size, size}}
for i = 1,6 do
if hasbit(val, bit(i)) then
for _,box in ipairs(boxes[i]) do
table.insert(fixed, box)
end
end
end
return {
type = "fixed",
fixed = fixed,
}
end
-- 'size' is the size of the junction cube without any connection, e.g. 1/8
-- 'boxes' is a table with 6 table elements for the 6 possible connection arms
-- 'tlib2' is the tubelib2 instance
-- 'node' is the node definition with tiles, callback functions, and so on
-- 'index' number for the inventory node (default 0)
function techage.register_junction(name, size, boxes, tlib2, node, index)
local names = {}
for idx = 0,63 do
local ndef = table.copy(node)
if idx == (index or 0) then
ndef.groups.not_in_creative_inventory = 0
else
ndef.groups.not_in_creative_inventory = 1
end
ndef.groups.techage_trowel = 1
ndef.drawtype = "nodebox"
ndef.node_box = get_node_box(idx, size, boxes)
ndef.paramtype2 = "facedir"
ndef.on_rotate = screwdriver.disallow
ndef.paramtype = "light"
ndef.use_texture_alpha = techage.CLIP
ndef.sunlight_propagates = true
ndef.is_ground_content = false
ndef.drop = name..(index or "0")
minetest.register_node(name..idx, ndef)
tlib2:add_secondary_node_names({name..idx})
-- for the case that 'tlib2.force_to_use_tubes' is set
tlib2:add_special_node_names({name..idx})
names[#names + 1] = name..idx
end
return names
end
local SideToDir = {B=1, R=2, F=3, L=4}
local function dir_to_dir2(dir, param2)
if param2 == 0 then
return dir
elseif param2 == 1 then
return ({4,1,2,3,5,6})[dir]
elseif param2 == 2 then
return ({3,4,1,2,5,6})[dir]
elseif param2 == 3 then
return ({2,3,4,1,5,6})[dir]
end
return dir
end
function techage.junction_type(pos, network, default_side, param2)
local connected = function(self, pos, dir)
if network:is_primary_node(pos, dir) then
local param2, npos = self:get_primary_node_param2(pos, dir)
if param2 then
local d1, d2, num = self:decode_param2(npos, param2)
dir = tubelib2.Turn180Deg[dir]
return d1 == dir or dir == d2
end
end
end
local val = 0
if default_side then
val = setbit(val, bit(SideToDir[default_side]))
end
for dir = 1,6 do
local dir2 = dir_to_dir2(dir, param2)
if network.force_to_use_tubes then
if connected(network, pos, dir) then
val = setbit(val, bit(dir2))
elseif network:is_special_node(pos, dir) then
val = setbit(val, bit(dir2))
end
else
if connected(network, pos, dir) then
val = setbit(val, bit(dir2))
elseif network:is_secondary_node(pos, dir) then
val = setbit(val, bit(dir2))
end
end
end
return val
end

View File

@ -16,9 +16,8 @@
local M = minetest.get_meta
local S = techage.S
local networks = techage.networks
local Cable = techage.ElectricCable
local power = techage.power
local power = networks.power
local size = 3/32
local Boxes = {
@ -30,33 +29,33 @@ local Boxes = {
{{-size, -size, -size, size, 0.5, size}}, -- y+
}
techage.register_junction("techage:electric_junction", 2/8, Boxes, Cable, {
local names = networks.register_junction("techage:electric_junction", 2/8, Boxes, Cable, {
description = S("TA Electric Junction Box"),
tiles = {"techage_electric_junction.png"},
use_texture_alpha = "clip",
is_ground_content = false,
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, techage_trowel = 1},
sounds = default.node_sound_defaults(),
after_place_node = function(pos, placer, itemstack, pointed_thing)
local name = "techage:electric_junction"..techage.junction_type(pos, Cable)
local name = "techage:electric_junction" .. networks.junction_type(pos, Cable)
minetest.swap_node(pos, {name = name, param2 = 0})
Cable:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, dir1, tlib2, node)
local name = "techage:electric_junction"..techage.junction_type(pos, Cable)
minetest.swap_node(pos, {name = name, param2 = 0})
power.update_network(pos, nil, tlib2)
if not networks.hidden_name(pos) then
local name = "techage:electric_junction" .. networks.junction_type(pos, Cable)
minetest.swap_node(pos, {name = name, param2 = 0})
end
power.update_network(pos, 0, tlib2, node)
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Cable:after_dig_node(pos)
end,
networks = {
ele1 = {
sides = networks.AllSides, -- connection sides for cables
ntype = "junc",
},
},
})
power.register_nodes(names, Cable, "junc")
minetest.register_craft({
output = "techage:electric_junction0 2",
recipe = {

View File

@ -1,262 +0,0 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
API for Power Nodes
]]--
--local P2S = minetest.pos_to_string
--local M = minetest.get_meta
--local N = function(pos) return minetest.get_node(pos).name end
--local S = techage.S
local net_def = techage.networks.net_def
local networks = techage.networks
-- Consumer States
local STOPPED = 1
local NOPOWER = 2
local RUNNING = 3
techage.power = {}
techage.power.STOPPED = STOPPED
techage.power.NOPOWER = NOPOWER
techage.power.RUNNING = RUNNING
-- determine network ID (largest hash number of all generators)
local function determine_netID(pos, outdir, Cable)
local netID = 0
networks.connection_walk(pos, outdir, Cable, function(pos, indir, node)
local ntype = net_def(pos, Cable.tube_type).ntype
if ntype ~= "junc" then
local new = minetest.hash_node_position(pos)
if netID <= new then
netID = new
end
end
end)
return netID
end
-- store network ID on each node
local function store_netID(pos, outdir, netID, Cable)
networks.connection_walk(pos, outdir, Cable, function(pos, indir, node)
--techage.mark_position("singleplayer", pos, "store", "", 2)-----------------------------------------
--print(node.name, dump(net_def(pos, Cable.tube_type)))
if net_def(pos, Cable.tube_type) then
local nvm = techage.get_nvm(pos)
nvm[Cable.tube_type] = nvm[Cable.tube_type] or {}
nvm[Cable.tube_type]["netID"] = netID
end
end)
end
-- delete network and ID on each node
local function delete_netID(pos, outdir, Cable)
local netID = 0
networks.connection_walk(pos, outdir, Cable, function(pos, indir, node)
--techage.mark_position("singleplayer", pos, "delete", "", 2)----------------------------------------
if net_def(pos, Cable.tube_type) then
local nvm = techage.get_nvm(pos)
if nvm[Cable.tube_type] and nvm[Cable.tube_type]["netID"] then
netID = nvm[Cable.tube_type]["netID"]
nvm[Cable.tube_type]["netID"] = nil
end
end
end)
networks.delete_network(Cable.tube_type, netID)
end
-- Keep the network up and running
local function trigger_network(pos, outdir, Cable)
local nvm = techage.get_nvm(pos)
local netID = nvm[Cable.tube_type] and nvm[Cable.tube_type]["netID"]
if not netID then
--print("determine_netID !!!!!!!!!!!!!!!!!!!!")
netID = determine_netID(pos, outdir, Cable)
store_netID(pos, outdir, netID, Cable)
networks.build_network(pos, outdir, Cable, netID)
elseif not networks.get_network(Cable.tube_type, netID) then
--print("build_network !!!!!!!!!!!!!!!!!!!!")
netID = determine_netID(pos, outdir, Cable)
store_netID(pos, outdir, netID, Cable)
networks.build_network(pos, outdir, Cable, netID)
end
end
local function build_network_consumer(pos, Cable)
local outdirs = techage.networks.get_node_connections(pos, Cable.tube_type)
if #outdirs == 1 then
local netID = determine_netID(pos, outdirs[1], Cable)
store_netID(pos, outdirs[1], netID, Cable)
networks.build_network(pos, outdirs[1], Cable, netID)
end
end
-- To be called from each node via 'tubelib2_on_update2'
-- 'output' is optional and only needed for nodes with dedicated
-- pipe sides (e.g. pumps).
function techage.power.update_network(pos, outdir, Cable)
networks.node_connections(pos, Cable) -- update node internal data
delete_netID(pos, outdir, Cable) -- network walk to delete all IDs
end
--
-- Read the current power value from all connected devices (used for solar cells)
-- Only used by the solar inverter to collect the power of all solar cells.
-- Only one inverter per network is allowed. Therefore, we have to check,
-- if additional inverters are in the network.
-- Function returns in addition the number of found inverters.
function techage.power.get_power(pos, outdir, Cable, inverter)
local sum = 0
local num_inverter = 0
networks.connection_walk(pos, outdir, Cable, function(pos, indir, node)
--techage.mark_position("singleplayer", pos, "get_power", "", 2)-----------------------------------------
local def = net_def(pos, Cable.tube_type)
if def and def.on_getpower then
sum = sum + def.on_getpower(pos)
else
local node = techage.get_node_lvm(pos)
if node.name == inverter then
num_inverter = num_inverter + 1
end
end
end)
return sum, num_inverter
end
--
-- Consumer related functions
--
-- function checks for a power grid, not for enough power
function techage.power.power_available(pos, Cable)
local nvm = techage.get_nvm(pos)
local tlib_type = Cable.tube_type
local netID = nvm[Cable.tube_type] and nvm[Cable.tube_type]["netID"]
local netw = networks.has_network(tlib_type, netID)
return netw and netw.on and netw.alive and netw.alive > 0
end
function techage.power.network_overloaded(pos, Cable)
local nvm = techage.get_nvm(pos)
local tlib_type = Cable.tube_type
local netID = nvm[Cable.tube_type] and nvm[Cable.tube_type]["netID"]
local netw = networks.has_network(tlib_type, netID)
if netw then
local sum = (netw.available1 or 0) + (netw.available2 or 0)
return sum > 0 and sum < (netw.needed1 or 0)
end
end
-- this is more a try to start, the start will be performed by on_power()
function techage.power.consumer_start(pos, Cable, cycle_time)
local nvm = techage.get_nvm(pos)
local tlib_type = Cable.tube_type
nvm[tlib_type] = nvm[tlib_type] or {}
nvm[tlib_type]["calive"] = (cycle_time / 2) + 1
nvm[tlib_type]["cstate"] = NOPOWER
nvm[tlib_type]["taken"] = 0
end
function techage.power.consumer_stop(pos, Cable)
local nvm = techage.get_nvm(pos)
local tlib_type = Cable.tube_type
nvm[tlib_type] = nvm[tlib_type] or {}
nvm[tlib_type]["calive"] = -1
nvm[tlib_type]["cstate"] = STOPPED
nvm[tlib_type]["taken"] = 0
end
function techage.power.consumer_alive(pos, Cable, cycle_time)
local nvm = techage.get_nvm(pos)
local def = nvm[Cable.tube_type] -- power related network data
if def then
-- if network is deleted (cable removed/placed) rebuild it to prevent flickering lights
if not def["netID"] or not networks.get_network(Cable.tube_type, def["netID"]) then
build_network_consumer(pos, Cable)
end
local rv = (cycle_time / 2) + 1
if def["netID"] and def["calive"] and def["calive"] < rv then -- network available
def["calive"] = rv
return def["taken"] or 0
elseif not def["cstate"] or def["cstate"] == RUNNING then
local ndef = net_def(pos, Cable.tube_type)
ndef.on_nopower(pos, Cable.tube_type)
def["cstate"] = NOPOWER
end
else
local ndef = net_def(pos, Cable.tube_type)
ndef.on_nopower(pos, Cable.tube_type)
end
return 0
end
--
-- Generator related functions
--
-- curr_power is optional, only needed for generators with variable output power
function techage.power.generator_start(pos, Cable, cycle_time, outdir, curr_power)
local nvm = techage.get_nvm(pos)
local tlib_type = Cable.tube_type
nvm[tlib_type] = nvm[tlib_type] or {}
nvm[tlib_type]["galive"] = (cycle_time / 2) + 2
nvm[tlib_type]["gstate"] = RUNNING
nvm[tlib_type]["given"] = 0
nvm[tlib_type]["curr_power"] = curr_power
trigger_network(pos, outdir, Cable)
end
function techage.power.generator_stop(pos, Cable, outdir)
local nvm = techage.get_nvm(pos)
local tlib_type = Cable.tube_type
nvm[tlib_type] = nvm[tlib_type] or {}
nvm[tlib_type]["galive"] = -1
nvm[tlib_type]["gstate"] = STOPPED
nvm[tlib_type]["given"] = 0
end
-- curr_power is optional, only needed for generators with variable output power
function techage.power.generator_alive(pos, Cable, cycle_time, outdir, curr_power)
local nvm = techage.get_nvm(pos)
local def = nvm[Cable.tube_type] -- power related network data
if def then
trigger_network(pos, outdir, Cable)
def["galive"] = (cycle_time / 2) + 2
def["curr_power"] = curr_power
return def["given"] or 0
end
return 0
end
-- Calculate the needed power over all con1 consumers
function techage.power.needed_power(pos, Cable, outdir)
local sum = 0
networks.connection_walk(pos, outdir, Cable, function(pos, indir, node)
local net = net_def(pos, Cable.tube_type) -- network definition
if net.ntype == "con1" then
local nvm = techage.get_nvm(pos)
local def = nvm[Cable.tube_type] -- power related data
if def and def["cstate"] and def["cstate"] ~= STOPPED then
if def["calive"] >= 0 then
sum = sum + (net.nominal or def.curr_power or 0)
end
end
end
end)
return sum
end
-- function delete_netID(pos, outdir, Cable)
techage.power.delete_netID = delete_netID

View File

@ -16,9 +16,8 @@ local P = minetest.string_to_pos
local M = minetest.get_meta
local S = techage.S
local networks = techage.networks
local Cable = techage.ElectricCable
local power = techage.power
local power = networks.power
local function can_dig(pos, digger)
if M(pos):get_string("owner") == digger:get_player_name() then
@ -44,10 +43,7 @@ minetest.register_node("techage:power_line", {
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
if oldmetadata and oldmetadata.fields and oldmetadata.fields.tl2_param2 then
oldnode.param2 = oldmetadata.fields.tl2_param2
Cable:after_dig_tube(pos, oldnode)
end
Cable:after_dig_tube(pos, oldnode)
end,
paramtype2 = "facedir", -- important!
@ -86,10 +82,7 @@ minetest.register_node("techage:power_lineS", {
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
if oldmetadata and oldmetadata.fields and oldmetadata.fields.tl2_param2 then
oldnode.param2 = oldmetadata.fields.tl2_param2
Cable:after_dig_tube(pos, oldnode)
end
Cable:after_dig_tube(pos, oldnode)
end,
paramtype2 = "facedir", -- important!
@ -134,10 +127,7 @@ minetest.register_node("techage:power_lineA", {
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
if oldmetadata and oldmetadata.fields and oldmetadata.fields.tl2_param2 then
oldnode.param2 = oldmetadata.fields.tl2_param2
Cable:after_dig_tube(pos, oldnode)
end
Cable:after_dig_tube(pos, oldnode)
end,
paramtype2 = "facedir", -- important!
@ -214,13 +204,7 @@ minetest.register_node("techage:power_pole2", {
end,
can_dig = can_dig,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
if oldmetadata and oldmetadata.fields and oldmetadata.fields.tl2_param2 then
oldnode.param2 = oldmetadata.fields.tl2_param2
Cable:after_dig_tube(pos, oldnode)
end
end,
tubelib2_on_update2 = function(pos, dir1, tlib2, node)
power.update_network(pos, nil, tlib2)
Cable:after_dig_tube(pos, oldnode)
end,
on_rotate = screwdriver.disallow, -- important!
@ -304,20 +288,10 @@ minetest.register_node("techage:power_pole_conn", {
},
connects_to = {"techage:power_line", "techage:power_lineS", "techage:power_lineA"},
-- after_place_node -- see techage:power_pole
tubelib2_on_update2 = function(pos, dir1, tlib2, node)
power.update_network(pos, nil, tlib2)
end,
can_dig = can_dig,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Cable:after_dig_node(pos)
end,
can_dig = can_dig,
networks = {
ele1 = {
sides = networks.AllSides, -- connection sides for cables
ntype = "junc",
},
},
drop = "techage:power_pole",
on_rotate = screwdriver.disallow, -- important!
@ -329,8 +303,7 @@ minetest.register_node("techage:power_pole_conn", {
sounds = default.node_sound_defaults(),
})
Cable:add_secondary_node_names({"techage:power_pole_conn"})
power.register_nodes({"techage:power_pole_conn"}, Cable, "junc")
minetest.register_node("techage:power_pole3", {
description = S("TA Power Pole"),

View File

@ -12,210 +12,4 @@
]]--
-- for lazy programmers
local S2P = minetest.string_to_pos
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local M = minetest.get_meta
local N = function(pos) return minetest.get_node(pos).name end
local S = techage.S
local CYCLE_TIME = 2
local Cable = techage.ElectricCable
local power = techage.power
local networks = techage.networks
local STOPPED = techage.power.STOPPED
local NOPOWER = techage.power.NOPOWER
local RUNNING = techage.power.RUNNING
local function generator_data(gen_tbl)
local tbl = {
pow_all=0, pow_on=0, pow_act=0, pow_used=0,
num_on=0, num_act=0, num_used=0
}
for i,gen in ipairs(gen_tbl or {}) do
local nvm = techage.get_nvm(gen.pos)
tbl.pow_all = tbl.pow_all + (gen.nominal or 0)
if nvm.ele1 and nvm.ele1.gstate and nvm.ele1.gstate ~= STOPPED then
tbl.num_on = tbl.num_on + 1
tbl.pow_on = tbl.pow_on + (nvm.ele1.curr_power or gen.nominal or 0)
if (nvm.ele1.galive or -1) >= 0 then
tbl.num_act = tbl.num_act + 1
tbl.pow_act = tbl.pow_act + (nvm.ele1.curr_power or gen.nominal or 0)
if (nvm.ele1.given or 0) > 0 then
tbl.num_used = tbl.num_used + 1
tbl.pow_used = tbl.pow_used + (nvm.ele1.given or 0)
end
end
end
end
tbl.num_all = #(gen_tbl or {})
return tbl
end
local function consumer_data(con_tbl)
local tbl = {
pow_all=0, pow_on=0, pow_act=0, pow_used=0,
num_on=0, num_act=0, num_used=0
}
for i,gen in ipairs(con_tbl or {}) do
local nvm = techage.get_nvm(gen.pos)
tbl.pow_all = tbl.pow_all + (gen.nominal or 0)
if nvm.ele1 and nvm.ele1.cstate and nvm.ele1.cstate ~= STOPPED then
tbl.num_on = tbl.num_on + 1
tbl.pow_on = tbl.pow_on + (gen.nominal or 0)
if (nvm.ele1.calive or -1) >= 0 then
tbl.num_act = tbl.num_act + 1
tbl.pow_act = tbl.pow_act + (gen.nominal or 0)
if (nvm.ele1.taken or 0) > 0 then
tbl.num_used = tbl.num_used + 1
tbl.pow_used = tbl.pow_used + (nvm.ele1.taken or 0)
end
end
end
end
tbl.num_all = #(con_tbl or {})
return tbl
end
local function calc_network_data(pos, nvm)
local netw = techage.networks.has_network("ele1", nvm.ele1 and nvm.ele1.netID) or {}
local gen1 = generator_data(netw.gen1)
local gen2 = generator_data(netw.gen2)
local con1 = consumer_data(netw.con1)
local con2 = consumer_data(netw.con2)
return netw, gen1, gen2, con1, con2
end
local function column(x,y, data)
return
"label["..x..","..(y+0.0)..";"..data.num_all.. " ("..data.pow_all.." ku)]"..
"label["..x..","..(y+0.5)..";"..data.num_on.. " ("..data.pow_on.." ku)]"..
"label["..x..","..(y+1.0)..";"..data.num_act.. " ("..data.pow_act.." ku)]"..
"label["..x..","..(y+1.5)..";"..data.num_used.." ("..data.pow_used.." ku)]"
end
local function get_state(netw, gen1, gen2, con1, con2)
local num_nodes = gen1.num_all + gen2.num_all + con1.num_all +
con2.num_all + (#(netw.junc or {})) + (#(netw.term or {}))
local nload = (gen1.pow_act + gen2.pow_act) / con1.pow_act
local state = S("Number of all nodes")..": ".. num_nodes
if not netw.gen1 and not netw.gen2 then
state = S("No network or active generator available!")
elseif num_nodes > (techage.ELE1_MAX_CABLE_LENGHT - 50) then
state = string.format(S("With %u of a maximum of %u blocks you are almost at the limit!"),
num_nodes, techage.ELE1_MAX_CABLE_LENGHT)
elseif nload <= 1.0 then
state = S("The network is overloaded!")
elseif nload < 1.2 then
state = S("The network load is almost at the limit!")
end
return state
end
local function formspec(pos, nvm)
local netw, gen1, gen2, con1, con2 = calc_network_data(pos, nvm)
netw.prop = ((netw.prop or 0) + 1) % 2
local star = netw.prop == 1 and "*" or ""
local state = get_state(netw, gen1, gen2, con1, con2)
return "size[10,7]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"box[0,-0.1;9.8,0.5;#c6e8ff]"..
"label[4,-0.1;"..minetest.colorize( "#000000", S("Network Data")).."]"..
"label[9.5,-0.1;"..minetest.colorize( "#000000", star).."]"..
power.formspec_label_bar(pos, 0, 0.7, S("Genera. 1"), gen1.pow_act, gen1.pow_used)..
power.formspec_label_bar(pos, 2.5, 0.7, S("Genera. 2"), gen2.pow_act, gen2.pow_used)..
power.formspec_label_bar(pos, 5, 0.7, S("Consum. 2"), con2.pow_act, con2.pow_used)..
power.formspec_label_bar(pos, 7.5, 0.7, S("Consum. 1"), con1.pow_act, con1.pow_used)..
"box[0,4.3;9.8,0.4;#c6e8ff]"..
"box[0,4.85;9.8,0.4;#395c74]"..
"box[0,5.35;9.8,0.4;#395c74]"..
"box[0,5.85;9.8,0.4;#395c74]"..
"box[0,6.35;9.8,0.4;#395c74]"..
"label[2,4.3;"..minetest.colorize( "#000000", S("Genera. 1")).."]"..
"label[4,4.3;"..minetest.colorize( "#000000", S("Genera. 2")).."]"..
"label[6,4.3;"..minetest.colorize( "#000000", S("Consum. 2")).."]"..
"label[8,4.3;"..minetest.colorize( "#000000", S("Consum. 1")).."]"..
"label[0.1,4.8;"..S("All nodes:").."]"..
"label[0.1,5.3;"..S("Turned on:").."]"..
"label[0.1,5.8;"..S("Active:").."]"..
"label[0.1,6.3;"..S("In use:").."]"..
"box[0,6.95;9.8,0.4;#000000]"..
"label[0.1,6.9;"..state.."]"..
column(2, 4.8, gen1)..
column(4, 4.8, gen2)..
column(6, 4.8, con2)..
column(8, 4.8, con1)
end
minetest.register_node("techage:power_terminal", {
description = S("TA3 Power Terminal Old"),
inventory_image = "techage_power_terminal_front.png",
tiles = {
"techage_power_terminal_top.png",
"techage_power_terminal_top.png",
"techage_power_terminal_side.png",
"techage_power_terminal_side.png",
"techage_power_terminal_back.png",
"techage_power_terminal_front.png",
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{ -8/16, -8/16, 0/16, 8/16, 8/16, 8/16},
},
},
after_place_node = function(pos)
local nvm = techage.get_nvm(pos)
M(pos):set_int("outdir", networks.side_to_outdir(pos, "B"))
Cable:after_place_node(pos)
M(pos):set_string("formspec", formspec(pos, nvm))
end,
after_dig_node = function(pos)
Cable:after_dig_node(pos)
techage.del_mem(pos)
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
end,
on_rightclick = function(pos, node, clicker)
techage.set_activeformspec(pos, clicker)
minetest.get_node_timer(pos):start(CYCLE_TIME)
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec(pos, nvm))
end,
on_timer = function(pos, elapsed)
local nvm = techage.get_nvm(pos)
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec(pos, nvm))
end
return true
end,
networks = {
ele1 = {
sides = {B = 1}, -- Cable connection side
ntype = "term",
},
},
paramtype2 = "facedir",
paramtype = "light",
use_texture_alpha = techage.CLIP,
on_rotate = screwdriver.disallow,
sunlight_propagates = true,
is_ground_content = false,
groups = {cracky = 2, level = 2, not_in_creative_inventory = 1},
sounds = default.node_sound_metal_defaults(),
})
Cable:add_secondary_node_names({"techage:power_terminal"})
minetest.register_alias_force("techage:power_terminal", "techage:ta3_power_terminal")

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -22,417 +22,121 @@ local S = techage.S
local CYCLE_TIME = 2
local Cable = techage.ElectricCable
local power = techage.power
local networks = techage.networks
local STOPPED = techage.power.STOPPED
local NOPOWER = techage.power.NOPOWER
local RUNNING = techage.power.RUNNING
local power = networks.power
local control = networks.control
local HELP = [[Commands
help print this text
cls clear screen
gen1 print all cat. 1 generators
gen2 print all cat. 2 generators
con2 print all cat. 2 consumers
num print number of network blocks
pow print provided and needed power]]
local HELP = S([[Commands
help . . . print this text
cls . . . . . clear screen
gen . . . . print all generators
sto . . . . . print all storage systems
]])
local Generators = {
S("Power station"),
S("Tiny generator"),
S("Solar system") ,
S("Wind turbine"),
S("Accu Box"),
S("Energy storage"),
S("Fuel cell cat. 1"),
S("Fuel cell cat. 2"),
S("Electrolyzer"),
S("TA2 Generator"),
}
local Storage = {
[S("Accu Box")] = true,
[S("Energy storage")] = true,
[S("Fuel cell cat. 1")] = true,
[S("Fuel cell cat. 2")] = true,
[S("Electrolyzer")] = true,
}
local GeneratorPerformances = {
80, -- S("Power station")
12, -- S("Tiny generator")
100, -- S("Solar system")
70, -- S("Wind turbine")
10, -- S("Accu Box")
60, -- S("Energy storage")
33, -- S("Fuel cell cat. 1")
34, -- S("Fuel cell cat. 2")
35, -- S("Electrolyzer")
24, -- S("TA2 Generator")
}
--
-- Generate the needed tables for the formspec
--
local Gentypes = table.concat(Generators, ",")
local Gentype2Idx = {}
local Gentype2Maxvalue = {}
local Gentype = {}
for idx,name in ipairs(Generators) do
Gentype2Idx[name] = idx
Gentype2Maxvalue[name] = GeneratorPerformances[idx]
Gentype[GeneratorPerformances[idx]] = name
local function row(num, label, data)
local y = 4.0 + num * 0.5
return
"box[0," .. y .. ";9.8,0.4;#395c74]"..
"label[0.2,"..y..";" .. label .. "]" ..
"label[8.5,"..y..";" .. data .. "]"
end
local function short_node_name(nominal)
return Gentype[nominal or 1] or "unknown"
end
local function generator_data(gen_tbl, nominal)
local pow_max = 0
local pow_curr = 0
local num_nodes = 0
for i,gen in ipairs(gen_tbl or {}) do
if gen.nominal == nominal then
local nvm = techage.get_nvm(gen.pos)
if nvm.ele1 and nvm.ele1.gstate and nvm.ele1.galive and nvm.ele1.given then
num_nodes = num_nodes + 1
if nvm.ele1.gstate == RUNNING then
pow_max = pow_max + (nvm.ele1.curr_power or nominal)
if nvm.ele1.galive > 0 and nvm.ele1.given > 0 then
pow_curr = pow_curr + nvm.ele1.given
end
end
end
end
end
local function formspec1(pos, data)
local mem = techage.get_mem(pos)
local outdir = M(pos):get_int("outdir")
local netw = networks.get_network_table(pos, Cable, outdir, true) or {}
data = data or power.get_network_data(pos, Cable, outdir)
return pow_max, pow_curr, num_nodes
end
local function get_generator_data(gen)
local nvm = techage.get_nvm(gen.pos)
local pow_max = 0
local pow_curr = 0
if nvm.ele1 and nvm.ele1.gstate and nvm.ele1.galive and nvm.ele1.given then
if nvm.ele1.gstate == RUNNING then
if nvm.ele1.curr_power and nvm.ele1.curr_power > 0 then
pow_max = nvm.ele1.curr_power
else
pow_max = gen.nominal
end
if nvm.ele1.galive > 0 and nvm.ele1.given > 0 then
pow_curr = nvm.ele1.given
end
end
end
return pow_curr, pow_max
end
local function get_consumer_data(gen)
local nvm = techage.get_nvm(gen.pos)
local pow_max = 0
local pow_curr = 0
if nvm.ele1 and nvm.ele1.cstate and nvm.ele1.calive and nvm.ele1.taken then
if nvm.ele1.cstate == RUNNING then
pow_max = gen.nominal
if nvm.ele1.calive > 0 and nvm.ele1.taken > 0 then
pow_curr = nvm.ele1.taken
end
end
end
return pow_curr, pow_max
end
local function consumer_data(gen_tbl, nominal)
local pow_max = 0
local pow_curr = 0
local num_nodes = 0
for i,gen in ipairs(gen_tbl or {}) do
if gen.nominal == nominal then
local nvm = techage.get_nvm(gen.pos)
if nvm.ele1 and nvm.ele1.cstate and nvm.ele1.calive and nvm.ele1.taken then
num_nodes = num_nodes + 1
if nvm.ele1.cstate == RUNNING then
pow_max = pow_max + nominal
if nvm.ele1.calive > 0 and nvm.ele1.taken > 0 then
pow_curr = pow_curr + nvm.ele1.taken
end
end
end
end
end
mem.star = ((mem.star or 0) + 1) % 2
local star = mem.star == 1 and "*" or ""
local storage_provided = math.max(data.consumed - data.available, 0)
local available = math.max(data.consumed, data.available)
return pow_max, pow_curr, num_nodes
end
local function storage_load(gen_tbl, nominal)
local load_curr = 0 -- percentage
local num = 0
for i,gen in ipairs(gen_tbl or {}) do
if gen.nominal == nominal then
local ndef = techage.NodeDef[techage.get_node_lvm(gen.pos).name]
if ndef and ndef.on_recv_message then
local resp, _ = ndef.on_recv_message(gen.pos, "0", "load")
if type(resp) == "number" then
load_curr = load_curr + resp
num = num + 1
end
end
end
end
if num > 0 then
return math.floor(load_curr / num)
else
return 0
end
end
local function calc_network_data_type(pos, nvm, gentype)
local pow_max1, pow_curr1, num_nodes1, pow_stored1
local pow_max2, pow_curr2, num_nodes2, pow_stored2
local nominal = Gentype2Maxvalue[gentype]
local netw = techage.networks.has_network("ele1", nvm.ele1 and nvm.ele1.netID) or {}
if gentype == S("Accu Box") or gentype == S("Energy storage") then
pow_max1, pow_curr1, num_nodes1 = generator_data(netw.gen2, nominal)
pow_max2, pow_curr2, num_nodes2 = consumer_data(netw.con2, nominal)
pow_stored1 = storage_load(netw.con2, Gentype2Maxvalue[gentype]).." %"
pow_stored2 = pow_stored1
elseif gentype == S("Fuel cell cat. 2") then
pow_max1, pow_curr1, num_nodes1 = generator_data(netw.gen2, nominal)
pow_max2, pow_curr2, num_nodes2 = 0, 0, 0
pow_stored1 = storage_load(netw.gen2, Gentype2Maxvalue[gentype]).." %"
pow_stored2 = "-"
elseif gentype == S("Fuel cell cat. 1") then
pow_max1, pow_curr1, num_nodes1 = generator_data(netw.gen1, nominal)
pow_max2, pow_curr2, num_nodes2 = 0, 0, 0
pow_stored1 = storage_load(netw.gen1, Gentype2Maxvalue[gentype]).." %"
pow_stored2 = "-"
elseif gentype == S("Electrolyzer") then
pow_max1, pow_curr1, num_nodes1 = 0, 0, 0
pow_max2, pow_curr2, num_nodes2 = consumer_data(netw.con2, nominal)
pow_stored2 = storage_load(netw.con2, Gentype2Maxvalue[gentype]).." %"
pow_stored1 = "-"
else -- gen1 generators
pow_max1, pow_curr1, num_nodes1 = generator_data(netw.gen1, nominal)
pow_max2, pow_curr2, num_nodes2 = 0, 0, 0
pow_stored1 = "-"
pow_stored2 = "-"
end
return netw,
{pow_max = pow_max1, pow_curr = pow_curr1, num_nodes = num_nodes1, pow_stored = pow_stored1},
{pow_max = pow_max2, pow_curr = pow_curr2, num_nodes = num_nodes2, pow_stored = pow_stored2}
end
local function calc_network_data_total(pos, nvm)
local netw = techage.networks.has_network("ele1", nvm.ele1 and nvm.ele1.netID) or {}
local pow_max1 = netw.available1 or 0
local pow_max2 = netw.available2 or 0
local pow_used1 = netw.on and math.min(netw.needed1 + netw.needed2, netw.available1) or 0
local pow_used2 = netw.on and math.max(netw.needed1 - pow_used1, -netw.available2) or 0
local num_nodes1 = #(netw.gen1 or {})
local num_nodes2 = #(netw.gen2 or {})
return netw,
{pow_max = pow_max1, pow_curr = pow_used1, num_nodes = num_nodes1},
{pow_max = pow_max2, pow_curr = pow_used2, num_nodes = num_nodes2}
end
local function get_state(netw)
local state = ""
local needed = techage.power.get_con1_sum(netw, "ele1") or 0
if #(netw.gen1 or {}) + #(netw.gen2 or {}) == 0 then
state = S("No power grid or running generator!")
elseif needed > (netw.available1 or 0) then
state = S("Probably too many consumers (")..needed.." "..S("ku is needed").."!)"
elseif (netw.num_nodes or 0) < techage.networks.MAX_NUM_NODES then
state = S("Number of power grid blocks")..": "..(netw.num_nodes or 0)..", "..S("Max. needed power")..": "..needed.. " ku"
else
state = S("To many blocks in the power grid!")
end
return state
end
local function column(x,y, data)
if data.pow_stored then
return
"label["..x..","..(y+0.0)..";"..data.num_nodes.. "]"..
"label["..x..","..(y+0.5)..";"..data.pow_max.. " ku]"..
"label["..x..","..(y+1.0)..";"..data.pow_curr.. " ku]"..
"label["..x..","..(y+1.5)..";"..data.pow_stored.."]"
else
return
"label["..x..","..(y+0.0)..";"..data.num_nodes.. "]"..
"label["..x..","..(y+0.5)..";"..data.pow_max.. " ku]"..
"label["..x..","..(y+1.0)..";"..data.pow_curr.. " ku]"
end
end
local function formspec_type(pos, nvm)
return "size[5,4]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"box[0,-0.1;4.8,0.5;#c6e8ff]"..
"label[1.5,-0.1;"..minetest.colorize( "#000000", S("Select type")).."]"..
"dropdown[0,1;5.2;gentype;"..Gentypes..";"..(nvm.gentype_idx or 1).."]"..
"style_type[button;bgcolor=#395c74]"..
"button[0,2.4;5,1;set;"..S("Store").."]"
end
local function formspec1(pos, nvm)
local gentype = nvm.gentype or S("Power station")
local netw, gen1, gen2 = calc_network_data_type(pos, nvm, gentype)
local _, sum1, sum2 = calc_network_data_total(pos, nvm)
netw.prop = ((netw.prop or 0) + 1) % 2
local star = netw.prop == 1 and "*" or ""
local state = get_state(netw)
return "size[11,9]"..
return "size[10,8]"..
"tabheader[0,0;tab;status,console;1;;true]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"box[0,-0.1;10.8,0.5;#c6e8ff]"..
"label[4.5,-0.1;"..minetest.colorize( "#000000", S("Network Data")).."]"..
"label[10.5,-0.1;"..minetest.colorize( "#000000", star).."]"..
"box[0,-0.1;9.8,0.5;#c6e8ff]"..
"label[0.2,-0.1;"..minetest.colorize( "#000000", S("Network Data")).."]"..
"label[9.5,-0.1;"..minetest.colorize( "#000000", star).."]"..
techage.formspec_power_bar(pos, 0.0, 0.7, S("Generator"), data.provided, data.available)..
techage.formspec_power_bar(pos, 2.5, 0.7, S("Consumer"), data.consumed, available)..
techage.formspec_charging_bar(pos, 5.0, 0.7, S("Charging"), data)..
techage.formspec_storage_bar(pos, 7.5, 0.7, S("Storage"), data.curr_load, data.max_capa)..
"style_type[button;bgcolor=#395c74]"..
"button[0,0.7;3,1;config;"..S("Type").."]"..
"box[0,1.6;10.8,0.4;#c6e8ff]"..
"box[0,2.15;10.8,0.4;#395c74]"..
"box[0,2.65;10.8,0.4;#395c74]"..
"box[0,3.15;10.8,0.4;#395c74]"..
"box[0,3.65;10.8,0.4;#395c74]"..
"label[0.1,1.55;"..minetest.colorize( "#000000", gentype).."]"..
"label[5.7,1.55;"..minetest.colorize( "#000000", S("Output")).."]"..
"label[8.2,1.55;"..minetest.colorize( "#000000", S("Intake")).."]"..
"label[0.1,2.1;"..S("Number blocks:").."]"..
"label[0.1,2.6;"..S("Maximum power:").."]"..
"label[0.1,3.1;"..S("Current power:").."]"..
"label[0.1,3.6;"..S("Energy stored:").."]"..
column(5.7, 2.1, gen1)..
column(8.2, 2.1, gen2)..
--"box[0,5.3;8.8,0.4;#c6e8ff]"..
"box[0,4.5;10.8,0.4;#c6e8ff]"..
"box[0,5.05;10.8,0.4;#395c74]"..
"box[0,5.55;10.8,0.4;#395c74]"..
"box[0,6.05;10.8,0.4;#395c74]"..
"label[0.1,4.45;"..minetest.colorize( "#000000", S("Power grid total")).."]"..
"label[5.7,4.45;"..minetest.colorize( "#000000", S("Generators")).."]"..
"label[8.2,4.45;"..minetest.colorize( "#000000", S("Storage systems")).."]"..
"label[0.1,5.0;"..S("Number blocks:").."]"..
"label[0.1,5.5;"..S("Maximum power:").."]"..
"label[0.1,6.0;"..S("Current power:").."]"..
column(5.7, 5.0, sum1)..
column(8.2, 5.0, sum2)..
"box[0,7.75;10.8,0.4;#000000]"..
"label[0.1,7.7;"..state.."]"
row(1, S("Number of network nodes:"), netw.num_nodes or 0) ..
row(2, S("Number of generators:"), #(netw.gen or {})) ..
row(3, S("Number of consumers:"), #(netw.con or {})) ..
row(4, S("Number of storage systems:"), #(netw.sto or {}))
end
local function formspec2(pos, mem)
local function formspec2(pos)
local mem = techage.get_mem(pos)
local meta = M(pos)
local output = meta:get_string("output")
local command = mem.cmnd or "help"
output = minetest.formspec_escape(output)
output = output:gsub("\n", ",")
return "size[11,9]"..
return "size[10,8]"..
"tabheader[0,0;tab;status,console;2;;true]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"box[0,-0.1;10.8,0.5;#c6e8ff]"..
"label[4.5,-0.1;"..minetest.colorize( "#000000", S("Network Data")).."]"..
"style_type[table,field;font=mono]"..
"table[0,0.5;10.8,7.8;output;"..output..";200]"..
"field[0.4,8.7;8.6,1;cmnd;;"..command.."]" ..
"box[0,-0.1;9.8,0.5;#c6e8ff]"..
"label[0.2,-0.1;"..minetest.colorize( "#000000", S("Network Data")).."]"..
--"style_type[table,field;font=mono]"..
"table[0,0.5;9.8,6.8;output;"..output..";200]"..
"field[0.4,7.7;7.6,1;cmnd;;"..command.."]" ..
"field_close_on_enter[cmnd;false]"..
"button[8.9,8.4;2,1;enter;"..S("Enter").."]"
"button[7.9,7.4;2,1;enter;"..S("Enter").."]"
end
local function generators(pos, gen_tbl)
local function generators(pos)
local tbl = {}
for _, item in ipairs(gen_tbl) do
if item and item.pos then
local node = techage.get_node_lvm(item.pos)
local ndef = minetest.registered_nodes[node.name]
local name = short_node_name(item.nominal)
local spos = P2S(item.pos)
local pow_curr, pow_max = get_generator_data(item, ndef)
if Storage[name] then
local load_percent = 0
local tdef = techage.NodeDef[node.name]
if tdef and tdef.on_recv_message then
load_percent = tdef.on_recv_message(item.pos, "0", "load") or 0
end
local s = string.format("%-16s %s = %u/%u ku (%u %%)",
spos, name, pow_curr, pow_max, load_percent)
tbl[#tbl + 1] = s
else
local s = string.format("%-16s %s = %u/%u ku", spos, name, pow_curr, pow_max)
tbl[#tbl + 1] = s
end
local outdir = M(pos):get_int("outdir")
local resp = control.request(pos, Cable, outdir, "gen", "info")
for _, item in ipairs(resp) do
local name = item.type .. " (" .. item.number .. ")"
if item.running then
local s = string.format("%s (%s): %s/%u ku (%s)",
item.type, item.number, techage.round(item.provided), item.available, item.termpoint)
tbl[#tbl + 1] = s
else
local s = string.format("%s (%s): off",
item.type, item.number)
tbl[#tbl + 1] = s
end
end
table.sort(tbl)
return table.concat(tbl, "\n")
end
local function consumers(pos, gen_tbl)
local function storages(pos)
local tbl = {}
for _, item in ipairs(gen_tbl) do
if item and item.pos then
local node = techage.get_node_lvm(item.pos)
local ndef = minetest.registered_nodes[node.name]
local name = short_node_name(item.nominal)
local spos = P2S(item.pos)
local pow_curr, pow_max = get_consumer_data(item, ndef)
if Storage[name] then
local load_percent = 0
local tdef = techage.NodeDef[node.name]
if tdef and tdef.on_recv_message then
load_percent = tdef.on_recv_message(item.pos, "0", "load") or 0
end
local s = string.format("%-16s %s = %u/%u ku (%u %%)",
spos, name, pow_curr, pow_max, load_percent)
tbl[#tbl + 1] = s
else
local s = string.format("%-16s %s = %u/%u ku", spos, name, pow_curr, pow_max)
tbl[#tbl + 1] = s
end
local outdir = M(pos):get_int("outdir")
local resp = control.request(pos, Cable, outdir, "sto", "info")
for _, item in ipairs(resp) do
local name = item.type .. " (" .. item.number .. ")"
if item.running then
local s = string.format("%s (%s): %s/%s kud",
item.type, item.number,
techage.round(item.load / techage.CYCLES_PER_DAY),
techage.round(item.capa / techage.CYCLES_PER_DAY))
tbl[#tbl + 1] = s
else
local s = string.format("%s (%s): %s/%s kud (off)",
item.type, item.number,
techage.round(item.load / techage.CYCLES_PER_DAY),
techage.round(item.capa / techage.CYCLES_PER_DAY))
tbl[#tbl + 1] = s
end
end
table.sort(tbl)
return table.concat(tbl, "\n")
end
local function number_nodes(pos, netw)
return
"num. generators cat. 1: " .. #(netw.gen1 or {}) .. "\n" ..
"num. generators cat. 2: " .. #(netw.gen2 or {}) .. "\n" ..
"num. consumers cat. 1: " .. #(netw.con1 or {}) .. "\n" ..
"num. consumers cat. 2: " .. #(netw.con2 or {})
end
local function power_network(pos, netw)
return
"pow. generators cat. 1: " .. (netw.available1 or 0) .. " ku\n" ..
"pow. generators cat. 2: " .. (netw.available2 or 0) .. " ku\n" ..
"pow. consumers cat. 1: " .. (netw.needed1 or 0) .. " ku\n" ..
"pow. consumers cat. 2: " .. (netw.needed2 or 0) .. " ku"
end
local function output(pos, command, text)
local meta = M(pos)
text = meta:get_string("output") .. "\n$ " .. command .. "\n" .. (text or "")
@ -446,26 +150,16 @@ local function command(pos, nvm, command)
if command then
command = command:sub(1,80)
command = string.trim(command)
local cmd, data = unpack(string.split(command, " ", false, 1))
if command == "cls" then
if cmd == "cls" then
meta:set_string("output", "")
elseif command == "help" then
elseif cmd == "help" then
output(pos, command, HELP)
elseif command == "gen1" then
local netw = techage.networks.has_network("ele1", nvm.ele1 and nvm.ele1.netID) or {}
output(pos, command, generators(pos, netw.gen1 or {}))
elseif command == "gen2" then
local netw = techage.networks.has_network("ele1", nvm.ele1 and nvm.ele1.netID) or {}
output(pos, command, generators(pos, netw.gen2 or {}))
elseif command == "con2" then
local netw = techage.networks.has_network("ele1", nvm.ele1 and nvm.ele1.netID) or {}
output(pos, command, consumers(pos, netw.con2 or {}))
elseif command == "num" then
local netw = techage.networks.has_network("ele1", nvm.ele1 and nvm.ele1.netID) or {}
output(pos, command, number_nodes(pos, netw))
elseif command == "pow" then
local netw = techage.networks.has_network("ele1", nvm.ele1 and nvm.ele1.netID) or {}
output(pos, command, power_network(pos, netw))
elseif cmd == "gen" then
output(pos, command, generators(pos))
elseif cmd == "sto" then
output(pos, command, storages(pos))
elseif command ~= "" then
output(pos, command, "")
end
@ -492,33 +186,32 @@ minetest.register_node("techage:ta3_power_terminal", {
},
after_place_node = function(pos)
local nvm = techage.get_nvm(pos)
M(pos):set_int("outdir", networks.side_to_outdir(pos, "B"))
Cable:after_place_node(pos)
M(pos):set_string("formspec", formspec1(pos, nvm))
M(pos):set_string("formspec", formspec1(pos))
end,
after_dig_node = function(pos)
Cable:after_dig_node(pos)
techage.del_mem(pos)
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
end,
on_rightclick = function(pos, node, clicker)
local mem = techage.get_mem(pos)
if mem.active_formspec == 2 then
M(pos):set_string("formspec", formspec2(pos, mem))
M(pos):set_string("formspec", formspec2(pos))
else
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", formspec1(pos, nvm))
M(pos):set_string("formspec", formspec1(pos))
minetest.get_node_timer(pos):start(CYCLE_TIME)
techage.set_activeformspec(pos, clicker)
mem.active_formspec = 1
end
end,
on_timer = function(pos, elapsed)
local nvm = techage.get_nvm(pos)
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec1(pos, nvm))
local outdir = M(pos):get_int("outdir")
local data = power.get_network_data(pos, Cable, outdir)
M(pos):set_string("formspec", formspec1(pos, data))
return true
end
return true
end,
on_receive_fields = function(pos, formname, fields, player)
@ -533,34 +226,20 @@ minetest.register_node("techage:ta3_power_terminal", {
mem.cmnd = ""
M(pos):set_string("formspec", formspec2(pos, mem))
mem.cmnd = fields.cmnd
elseif fields.config then
techage.reset_activeformspec(pos, player)
M(pos):set_string("formspec", formspec_type(pos, nvm))
elseif fields.set then
nvm.gentype = fields.gentype
nvm.gentype_idx = Gentype2Idx[fields.gentype] or 1
techage.set_activeformspec(pos, player)
M(pos):set_string("formspec", formspec1(pos, nvm))
elseif fields.tab == "1" then
M(pos):set_string("formspec", formspec1(pos, nvm))
M(pos):set_string("formspec", formspec1(pos))
techage.set_activeformspec(pos, player)
minetest.get_node_timer(pos):start(CYCLE_TIME)
mem.active_formspec = 1
elseif fields.tab == "2" then
M(pos):set_string("formspec", formspec2(pos, mem))
M(pos):set_string("formspec", formspec2(pos))
techage.reset_activeformspec(pos, player)
mem.active_formspec = 2
elseif fields.key_up and mem.cmnd then
M(pos):set_string("formspec", formspec2(pos, mem))
M(pos):set_string("formspec", formspec2(pos))
end
end,
networks = {
ele1 = {
sides = {B = 1}, -- Cable connection side
ntype = "term",
},
},
paramtype2 = "facedir",
paramtype = "light",
use_texture_alpha = techage.CLIP,
@ -571,7 +250,7 @@ minetest.register_node("techage:ta3_power_terminal", {
sounds = default.node_sound_metal_defaults(),
})
Cable:add_secondary_node_names({"techage:ta3_power_terminal"})
power.register_nodes({"techage:ta3_power_terminal"}, Cable, "con", {"B"})
minetest.register_craft({
output = "techage:ta3_power_terminal",

View File

@ -18,6 +18,7 @@ local M = minetest.get_meta
local S = techage.S
local Cable = techage.ElectricCable
local power = networks.power
local Param2ToDir = {
[0] = 6,
@ -28,9 +29,16 @@ local Param2ToDir = {
[5] = 3,
}
local function is_switchbox(pos)
return techage.get_node_lvm(pos).name == "techage:powerswitch_box" or
M(pos):get_string("techage_hidden_nodename") == "techage:powerswitch_box"
local function sign_in(pos, node)
local dir = Param2ToDir[node.param2]
local pos2 = tubelib2.get_pos(pos, dir)
M(pos2):set_int("switch_sign_in", 1)
end
local function sign_off(pos, node)
local dir = Param2ToDir[node.param2]
local pos2 = tubelib2.get_pos(pos, dir)
M(pos2):set_int("switch_sign_in", 0)
end
local function switch_on(pos, node, clicker, name)
@ -47,14 +55,8 @@ local function switch_on(pos, node, clicker, name)
local dir = Param2ToDir[node.param2]
local pos2 = tubelib2.get_pos(pos, dir)
if is_switchbox(pos2) then
if M(pos2):get_int("tl2_param2_copy") == 0 then
M(pos2):set_int("tl2_param2", techage.get_node_lvm(pos2).param2)
else
M(pos2):set_int("tl2_param2", M(pos2):get_int("tl2_param2_copy"))
end
Cable:after_place_tube(pos2, clicker)
end
techage.legacy_switches(pos2)
power.turn_switch_on(pos2, Cable, "techage:powerswitch_box_off", "techage:powerswitch_box_on")
end
local function switch_off(pos, node, clicker, name)
@ -72,13 +74,8 @@ local function switch_off(pos, node, clicker, name)
local dir = Param2ToDir[node.param2]
local pos2 = tubelib2.get_pos(pos, dir)
if is_switchbox(pos2) then
local node2 = techage.get_node_lvm(pos2)
node2.param2 = M(pos2):get_int("tl2_param2")
M(pos2):set_int("tl2_param2_copy", M(pos2):get_int("tl2_param2"))
M(pos2):set_int("tl2_param2", 0)
Cable:after_dig_tube(pos2, node2)
end
techage.legacy_switches(pos2)
power.turn_switch_off(pos2, Cable, "techage:powerswitch_box_off", "techage:powerswitch_box_on")
end
@ -106,12 +103,14 @@ minetest.register_node("techage:powerswitch", {
meta:set_string("infotext", S("TA Power Switch").." "..number)
local node = minetest.get_node(pos)
switch_on(pos, node, placer, "techage:powerswitch_on")
sign_in(pos, node)
end,
on_rightclick = function(pos, node, clicker)
switch_on(pos, node, clicker, "techage:powerswitch_on")
end,
after_dig_node = sign_off,
on_rotate = screwdriver.disallow,
paramtype = "light",
use_texture_alpha = techage.CLIP,
@ -143,6 +142,7 @@ minetest.register_node("techage:powerswitch_on", {
switch_off(pos, node, clicker, "techage:powerswitch")
end,
after_dig_node = sign_off,
drop = "techage:powerswitch",
on_rotate = screwdriver.disallow,
paramtype = "light",
@ -178,12 +178,14 @@ minetest.register_node("techage:powerswitchsmall", {
meta:set_string("infotext", S("TA Power Switch Small").." "..number)
local node = minetest.get_node(pos)
switch_on(pos, node, placer, "techage:powerswitchsmall_on")
sign_in(pos, node)
end,
on_rightclick = function(pos, node, clicker)
switch_on(pos, node, clicker, "techage:powerswitchsmall_on")
end,
after_dig_node = sign_off,
on_rotate = screwdriver.disallow,
paramtype = "light",
use_texture_alpha = techage.CLIP,
@ -215,6 +217,7 @@ minetest.register_node("techage:powerswitchsmall_on", {
switch_off(pos, node, clicker, "techage:powerswitchsmall")
end,
after_dig_node = sign_off,
drop = "techage:powerswitchsmall",
on_rotate = screwdriver.disallow,
paramtype = "light",

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -15,32 +15,59 @@
local S2P = minetest.string_to_pos
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local M = minetest.get_meta
local N = function(pos) return minetest.get_node(pos).name end
local N = techage.get_node_lvm
local S = techage.S
local Cable = techage.ElectricCable
local power = networks.power
-- primary power node
minetest.register_node("techage:powerswitch_box", {
description = S("TA Power Switch Box"),
tiles = {
-- up, down, right, left, back, front
'techage_electric_switch.png^[transformR90',
'techage_electric_switch.png^[transformR90',
'techage_electric_switch.png',
'techage_electric_switch.png',
'techage_electric_junction.png',
'techage_electric_junction.png',
local node_box = {
type = "fixed",
fixed = {
{ -1/4, -1/4, -2/4, 1/4, 1/4, 2/4},
},
}
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{ -1/4, -1/4, -2/4, 1/4, 1/4, 2/4},
},
},
function techage.legacy_switches(pos)
local meta = M(pos)
local node = N(pos)
if node.name == "techage:powerswitch_box" then
if meta:get_int("netw_param2") == 0 then
node.name = "techage:powerswitch_box_off"
else
node.name = "techage:powerswitch_box_on"
end
minetest.swap_node(pos, node)
elseif meta:get_string("netw_name") == "techage:powerswitch_box" then
if meta:get_int("netw_param2") == 0 then
meta:set_string("netw_name", "techage:powerswitch_box_off")
else
meta:set_string("netw_name", "techage:powerswitch_box_on")
end
end
if meta:contains("tl2_param2_copy") then
meta:set_string("netw_param2_copy", meta:get_string("tl2_param2_copy"))
meta:set_string("tl2_param2_copy", "")
end
end
-- The on-switch is a "primary node" like cables
minetest.register_node("techage:powerswitch_box_on", {
description = S("TA Power Switch Box"),
paramtype = "light",
drawtype = "nodebox",
node_box = node_box,
tiles = {
"techage_electric_switch.png^[transformR90",
"techage_electric_switch.png^[transformR90",
"techage_electric_switch.png",
"techage_electric_switch.png",
"techage_electric_junction.png",
"techage_electric_junction.png",
},
after_place_node = function(pos, placer, itemstack, pointed_thing)
if not Cable:after_place_tube(pos, placer, pointed_thing) then
minetest.remove_node(pos)
@ -48,23 +75,71 @@ minetest.register_node("techage:powerswitch_box", {
end
return false
end,
on_rightclick = function(pos, node, clicker)
techage.legacy_switches(pos)
if M(pos):get_int("switch_sign_in") ~= 1 then
if power.turn_switch_off(pos, Cable, "techage:powerswitch_box_off", "techage:powerswitch_box_on") then
minetest.sound_play("doors_glass_door_open", {
pos = pos,
gain = 1,
max_hear_distance = 5})
end
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Cable:after_dig_tube(pos, oldnode, oldmetadata)
end,
paramtype = "light",
use_texture_alpha = techage.CLIP,
sunlight_propagates = true,
on_rotate = screwdriver.disallow, -- important!
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2, techage_trowel = 1},
on_rotate = screwdriver.disallow,
use_texture_alpha = "clip",
sunlight_propagates = true,
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
groups = {choppy=2, cracky=2, crumbly=2, techage_trowel = 1},
sounds = default.node_sound_defaults(),
})
-- The off-switch is a "secondary node" without connection sides
minetest.register_node("techage:powerswitch_box_off", {
description = S("TA Power Switch Box"),
paramtype = "light",
drawtype = "nodebox",
node_box = node_box,
tiles = {
"techage_electric_switch_off.png^[transformR90",
"techage_electric_switch_off.png^[transformR90",
"techage_electric_switch_off.png",
"techage_electric_switch_off.png",
"techage_electric_junction.png",
"techage_electric_junction.png",
},
on_rightclick = function(pos, node, clicker)
techage.legacy_switches(pos)
if M(pos):get_int("switch_sign_in") ~= 1 then
if power.turn_switch_on(pos, Cable, "techage:powerswitch_box_off", "techage:powerswitch_box_on") then
minetest.sound_play("doors_glass_door_open", {
pos = pos,
gain = 1,
max_hear_distance = 5})
end
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Cable:after_dig_node(pos)
end,
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
use_texture_alpha = "clip",
sunlight_propagates = true,
is_ground_content = false,
drop = "techage:powerswitch_box_on",
groups = {choppy=2, cracky=2, crumbly=2, techage_trowel = 1, not_in_creative_inventory = 1},
sounds = default.node_sound_defaults(),
})
power.register_nodes({"techage:powerswitch_box_off"}, Cable, "con", {})
minetest.register_craft({
output = "techage:powerswitch_box",
output = "techage:powerswitch_box_on",
recipe = {
{"", "basic_materials:plastic_sheet", ""},
{"techage:electric_cableS", "basic_materials:copper_wire", "techage:electric_cableS"},

View File

@ -0,0 +1,71 @@
--[[
TechAge
=======
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
TA3 Old Power Switch Box
]]--
-- for lazy programmers
local S2P = minetest.string_to_pos
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local M = minetest.get_meta
local N = function(pos) return minetest.get_node(pos).name end
local S = techage.S
local Cable = techage.ElectricCable
local power = networks.power
local node_box = {
type = "fixed",
fixed = {
{ -1/4, -1/4, -2/4, 1/4, 1/4, 2/4},
},
}
-- legacy node
minetest.register_node("techage:powerswitch_box", {
description = S("TA Power Switch Box"),
tiles = {
-- up, down, right, left, back, front
'techage_electric_switch.png^[transformR90',
'techage_electric_switch.png^[transformR90',
'techage_electric_switch.png',
'techage_electric_switch.png',
'techage_electric_junction.png',
'techage_electric_junction.png',
},
drawtype = "nodebox",
node_box = node_box,
after_place_node = function(pos, placer, itemstack, pointed_thing)
local node = minetest.get_node(pos)
minetest.swap_node(pos, {name = "techage:powerswitch_box_on", param2 = node.param2})
if not Cable:after_place_tube(pos, placer, pointed_thing) then
minetest.remove_node(pos)
return true
end
return false
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Cable:after_dig_tube(pos, oldnode, oldmetadata)
end,
paramtype = "light",
use_texture_alpha = techage.CLIP,
sunlight_propagates = true,
on_rotate = screwdriver.disallow, -- important!
paramtype2 = "facedir",
drop = "techage:powerswitch_box_on",
groups = {choppy=2, cracky=2, crumbly=2, techage_trowel = 1, not_in_creative_inventory = 1},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})

View File

@ -1,83 +0,0 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
Global power Job Scheduler
]]--
-- for lazy programmers
local P2P = minetest.string_to_pos
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local M = minetest.get_meta
local N = function(pos) return minetest.get_node(pos).name end
local HEX = function(val) return string.format("%XH", val) end
local power = techage.power
local networks = techage.networks
local CYCLE_TIME = 1
techage.schedule = {}
local JobTable = {}
local JobQueue = {}
local first = 0
local last = -1
techage.SystemTime = 0
local function push(item)
last = last + 1
item.time = techage.SystemTime + CYCLE_TIME
JobQueue[last] = item
end
local function pop()
if first > last then return end
local item = JobQueue[first]
if item.time <= techage.SystemTime then
JobQueue[first] = nil -- to allow garbage collection
first = first + 1
return item
end
end
-- Scheduler
minetest.register_globalstep(function(dtime)
techage.SystemTime = techage.SystemTime + dtime
local item = pop()
local t = minetest.get_us_time()
while item do
local network = networks.peek_network(item.tube_type, item.netID)
if network and network.alive and network.alive >= 0 then
power.power_distribution(network, item.tube_type, item.netID, CYCLE_TIME)
network.alive = network.alive - 1
push(item)
else
JobTable[item.netID] = nil
networks.delete_network(item.tube_type, item.netID)
end
item = pop()
end
t = minetest.get_us_time() - t
if t > 10000 then
minetest.log("action", "[TA Schedule] duration="..t.."us")
end
end)
function techage.schedule.start(tube_type, netID)
if not JobTable[netID] then
local network = networks.peek_network(tube_type, netID)
power.power_distribution(network, tube_type, netID, CYCLE_TIME/2)
network.alive = network.alive - 1
push({tube_type = tube_type, netID = netID})
JobTable[netID] = true
end
end

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information

View File

@ -18,7 +18,7 @@ local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local power = techage.power
local power = networks.power
local ELE2_MAX_CABLE_LENGHT = 200
@ -40,13 +40,10 @@ local Cable = tubelib2.Tube:new({
end,
})
--Cable:register_on_tube_update(function(node, pos, out_dir, peer_pos, peer_in_dir)
-- local ndef = minetest.registered_nodes[node.name]
-- if ndef and ndef.after_tube_update then
-- minetest.registered_nodes[node.name].after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir)
-- end
--end)
-- Use global callback instead of node related functions
Cable:register_on_tube_update2(function(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2, node)
end)
minetest.register_node("techage:ta4_power_cableS", {
description = S("TA4 Low Power Cable"),
@ -155,17 +152,11 @@ minetest.register_node("techage:ta4_power_box", {
Cable:after_place_node(pos)
end,
tubelib2_on_update2 = function(pos, dir1, tlib2, node)
power.update_network(pos, nil, tlib2)
power.update_network(pos, 0, tlib2, node)
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
Cable:after_dig_node(pos)
end,
networks = {
ele2 = {
sides = {L=1, R=1, F=1, B=1},
ntype = "junc",
},
},
on_rotate = screwdriver.disallow, -- important!
paramtype = "light",
@ -176,7 +167,7 @@ minetest.register_node("techage:ta4_power_box", {
sounds = default.node_sound_defaults(),
})
Cable:add_secondary_node_names({"techage:ta4_power_box"})
power.register_nodes({"techage:ta4_power_box"}, Cable, "junc", {"L", "R", "F", "B"})
minetest.register_craft({
output = "techage:ta4_power_cableS 8",

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -20,45 +20,53 @@ local S2P = minetest.string_to_pos
local Cable = techage.ElectricCable
local Solar = techage.TA4_Cable
local power = techage.power
local networks = techage.networks
local power = networks.power
local control = networks.control
local CYCLE_TIME = 2
local PWR_PERF = 100
local COUNTDOWN_TICKS = 1
local function determine_power(pos, nvm)
-- determine DC node position
local outdir = M(pos):get_int("leftdir")
local max_power, num_inverter = power.get_power(pos, outdir, Solar, "techage:ta4_solar_inverter")
if num_inverter == 1 then
local netw = networks.get_network_table(pos, Solar, outdir) or {}
local num_inv = #(netw.con or {})
local max_power = 0
for _, power in ipairs(control.request(pos, Solar, outdir, "junc", "power")) do
max_power = max_power + power
end
if num_inv == 1 then -- only one inverter is allowed
nvm.max_power = math.min(PWR_PERF, max_power)
else
nvm.max_power = 0
end
return max_power, num_inverter
return max_power, num_inv
end
local function determine_power_from_time_to_time(pos, nvm)
local function has_dc_power(pos, nvm)
local time = minetest.get_timeofday() or 0
if time < 6.00/24.00 or time > 18.00/24.00 then
nvm.ticks = 0
nvm.max_power = 0
return
return false
end
nvm.ticks = nvm.ticks or 0
if (nvm.ticks % 10) == 0 then -- calculate max_power not to often
if (nvm.ticks % 30) == 0 then -- calculate max_power not to often
determine_power(pos, nvm)
else
nvm.max_power = nvm.max_power or 0
end
nvm.ticks = nvm.ticks + 1
return nvm.max_power > 0
end
local function formspec(self, pos, nvm)
local max_power = nvm.max_power or 0
local delivered = nvm.delivered or 0
local provided = nvm.provided or 0
local arrow = "image[2.5,1.5;1,1;techage_form_arrow_bg.png^[transformR270]"
if nvm.running then
if techage.is_running(nvm) then
arrow = "image[2.5,1.5;1,1;techage_form_arrow_fg.png^[transformR270]"
end
return "size[6,4]"..
@ -67,8 +75,8 @@ local function formspec(self, pos, nvm)
default.gui_slots..
"box[0,-0.1;5.8,0.5;#c6e8ff]"..
"label[2.5,-0.1;"..minetest.colorize( "#000000", S("Inverter")).."]"..
power.formspec_label_bar(pos, 0, 0.8, S("Power DC"), PWR_PERF, max_power)..
power.formspec_label_bar(pos, 3.5, 0.8, S("Power AC"), max_power, delivered)..
techage.formspec_power_bar(pos, 0, 0.8, S("Power DC"), max_power, PWR_PERF)..
techage.formspec_power_bar(pos, 3.5, 0.8, S("Power AC"), provided, max_power)..
arrow..
"image_button[2.5,3;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
"tooltip[2.5,3;1,1;"..self:get_state_tooltip(nvm).."]"
@ -76,30 +84,31 @@ end
local function can_start(pos, nvm, state)
local max_power, num_inverter = determine_power(pos, nvm)
if num_inverter > 1 then return "solar network error" end
if max_power == 0 then return "no solar power" end
if num_inverter > 1 then return S("solar network error") end
if max_power == 0 then return S("no solar power") end
return true
end
local function start_node(pos, nvm, state)
nvm.running = true
nvm.delivered = 0
local meta = M(pos)
nvm.provided = 0
nvm.ticks = 0
local outdir = M(pos):get_int("outdir")
power.generator_start(pos, Cable, CYCLE_TIME, outdir, nvm.max_power)
local outdir = meta:get_int("outdir")
power.start_storage_calc(pos, Cable, outdir)
techage.evaluate_charge_termination(nvm, meta)
end
local function stop_node(pos, nvm, state)
nvm.running = false
nvm.delivered = 0
nvm.provided = 0
nvm.running = nil -- legacy
local outdir = M(pos):get_int("outdir")
power.generator_stop(pos, Cable, outdir)
power.start_storage_calc(pos, Cable, outdir)
end
local State = techage.NodeStates:new({
node_name_passive = "techage:ta4_solar_inverter",
cycle_time = CYCLE_TIME,
standby_ticks = 0,
standby_ticks = 2,
formspec_func = formspec,
infotext_name = S("TA4 Solar Inverter"),
can_start = can_start,
@ -109,18 +118,30 @@ local State = techage.NodeStates:new({
local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos)
determine_power_from_time_to_time(pos, nvm)
--if nvm.max_power > 0 then
local outdir = M(pos):get_int("outdir")
nvm.delivered = power.generator_alive(pos, Cable, CYCLE_TIME, outdir, nvm.max_power)
--else
--nvm.delivered = 0
--end
local running = techage.is_running(nvm)
local has_power = has_dc_power(pos, nvm)
if running and not has_power then
State:standby(pos, nvm)
stop_node(pos, nvm, State)
elseif not running and has_power then
State:start(pos, nvm)
-- start_node() is called implicit
elseif running then
local meta = M(pos)
local outdir = meta:get_int("outdir")
local tp1 = tonumber(meta:get_string("termpoint1"))
local tp2 = tonumber(meta:get_string("termpoint2"))
nvm.provided = power.provide_power(pos, Cable, outdir, nvm.max_power, tp1, tp2)
local val = power.get_storage_load(pos, Cable, outdir, nvm.max_power)
if val > 0 then
nvm.load = val
end
State:keep_running(pos, nvm, COUNTDOWN_TICKS)
end
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
State:trigger_state(pos, nvm)
return true
return State:is_active(nvm)
end
local function on_receive_fields(pos, formname, fields, player)
@ -129,10 +150,6 @@ local function on_receive_fields(pos, formname, fields, player)
end
local nvm = techage.get_nvm(pos)
State:state_button_event(pos, nvm, fields)
if fields.update then
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
end
local function on_rightclick(pos, node, clicker)
@ -142,8 +159,11 @@ local function on_rightclick(pos, node, clicker)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
local function get_generator_data(pos, outdir, tlib2)
local nvm = techage.get_nvm(pos)
if techage.is_running(nvm) then
return {level = (nvm.load or 0) / nvm.max_power, perf = nvm.max_power, capa = nvm.max_power * 2}
end
end
minetest.register_node("techage:ta4_solar_inverter", {
@ -179,38 +199,48 @@ minetest.register_node("techage:ta4_solar_inverter", {
techage.del_mem(pos)
end,
tubelib2_on_update2 = tubelib2_on_update2,
on_receive_fields = on_receive_fields,
on_rightclick = on_rightclick,
on_timer = node_timer,
networks = {
ele1 = {
sides = {R = 1},
ntype = "gen1",
nominal = PWR_PERF,
regenerative = true,
},
ele2 = {
sides = {L = 1},
ntype = "con1",
},
}
get_generator_data = get_generator_data,
ta3_formspec = techage.generator_settings("ta4", PWR_PERF)
})
Cable:add_secondary_node_names({"techage:ta4_solar_inverter"})
Solar:add_secondary_node_names({"techage:ta4_solar_inverter"})
power.register_nodes({"techage:ta4_solar_inverter"}, Cable, "gen", {"R"})
power.register_nodes({"techage:ta4_solar_inverter"}, Solar, "con", {"L"})
techage.register_node({"techage:ta4_solar_inverter"}, {
on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "delivered" then
return math.floor((nvm.delivered or 0) + 0.5)
return math.floor((nvm.provided or 0) + 0.5)
else
return State:on_receive_message(pos, topic, payload)
end
end,
})
control.register_nodes({"techage:ta4_solar_inverter"}, {
on_receive = function(pos, tlib2, topic, payload)
end,
on_request = function(pos, tlib2, topic)
if topic == "info" then
local nvm = techage.get_nvm(pos)
local meta = M(pos)
return {
type = S("TA4 Solar Inverter"),
number = meta:get_string("node_number") or "",
running = techage.is_running(nvm) or false,
available = nvm.max_power or 0,
provided = nvm.provided or 0,
termpoint = meta:get_string("termpoint"),
}
end
return false
end,
}
)
minetest.register_craft({
output = "techage:ta4_solar_inverter",
recipe = {
@ -220,11 +250,6 @@ minetest.register_craft({
},
})
--minetest.register_craft({
-- output = "techage:ta4_solar_inverterDC",
-- recipe = {
-- {'default:steel_ingot', 'dye:green', 'default:steel_ingot'},
-- {'techage:ta4_power_cableS', '', ''},
-- {'default:steel_ingot', "techage:baborium_ingot", 'default:steel_ingot'},
-- },
--})
techage.register_node_for_v1_transition({"techage:ta4_solar_inverter"}, function(pos, node)
power.update_network(pos, nil, Solar)
end)

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -22,7 +22,7 @@ local PWR_PERF = 1
local PWR_CAPA = 2400 -- ticks (2s) with 1 ku ==> 80 min = 4 game days
local Cable = techage.ElectricCable
local power = techage.power
local power = networks.power
local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos)
@ -34,7 +34,6 @@ local function node_timer(pos, elapsed)
if t > 0.25 and t < 0.75 then
if nvm.providing then
power.generator_stop(pos, Cable, 5)
nvm.providing = false
nvm.provided = 0
end
@ -44,14 +43,14 @@ local function node_timer(pos, elapsed)
else
if nvm.capa > 0 then
if not nvm.providing then
power.generator_start(pos, Cable, CYCLE_TIME, 5)
power.start_storage_calc(pos, Cable, 5)
nvm.providing = true
else
nvm.provided = power.generator_alive(pos, Cable, CYCLE_TIME, 5)
nvm.provided = power.provide_power(pos, Cable, 5, PWR_PERF)
nvm.capa = nvm.capa - nvm.provided
end
else
power.generator_stop(pos, Cable, 5)
power.start_storage_calc(pos, Cable, 5)
nvm.providing = false
nvm.provided = 0
nvm.capa = 0
@ -78,18 +77,6 @@ local function after_dig_node(pos, oldnode, oldmetadata)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
end
local net_def = {
ele1 = {
sides = {D = 1},
ntype = "gen1",
nominal = PWR_PERF,
},
}
minetest.register_node("techage:ta4_solar_minicell", {
description = S("TA4 Streetlamp Solar Cell"),
tiles = {
@ -114,11 +101,9 @@ minetest.register_node("techage:ta4_solar_minicell", {
after_place_node = after_place_node,
after_dig_node = after_dig_node,
on_timer = node_timer,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
})
Cable:add_secondary_node_names({"techage:ta4_solar_minicell"})
power.register_nodes({"techage:ta4_solar_minicell"}, Cable, "gen", {"D"})
techage.register_node({"techage:ta4_solar_minicell"}, {
on_recv_message = function(pos, src, topic, payload)

View File

@ -20,7 +20,8 @@ local S = techage.S
local PWR_PERF = 3
local Cable = techage.TA4_Cable
local power = techage.power
local power = networks.power
local control = networks.control
local function temperature(pos)
local data = minetest.get_biome_data(pos)
@ -32,7 +33,7 @@ end
-- return the required param2 for solar modules
local function get_param2(pos, side)
local dir = techage.networks.side_to_outdir(pos, side)
local dir = networks.side_to_outdir(pos, side)
return (dir + 1) % 4
end
@ -89,25 +90,9 @@ local function after_dig_node(pos, oldnode)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, nil, tlib2)
power.update_network(pos, 0, tlib2, node)
end
local net_def1 = {
ele2 = {
sides = {F=1, B=1},
ntype = "junc",
on_getpower = on_getpower1,
},
}
local net_def2 = {
ele2 = {
sides = {F=1, B=1},
ntype = "junc",
on_getpower = on_getpower2,
},
}
minetest.register_node("techage:ta4_solar_module", {
description = S("TA4 Solar Module"),
inventory_image = "techage_solar_module_top.png",
@ -170,7 +155,6 @@ minetest.register_node("techage:ta4_solar_carrier", {
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def1,
paramtype = "light",
use_texture_alpha = techage.CLIP,
@ -210,7 +194,6 @@ minetest.register_node("techage:ta4_solar_carrierB", {
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def2,
paramtype = "light",
use_texture_alpha = techage.CLIP,
@ -249,8 +232,29 @@ minetest.register_node("techage:ta4_solar_carrierT", {
sounds = default.node_sound_stone_defaults(),
})
Cable:add_secondary_node_names({"techage:ta4_solar_carrier", "techage:ta4_solar_carrierB"})
power.register_nodes({"techage:ta4_solar_carrier", "techage:ta4_solar_carrierB"}, Cable, "junc", {"F", "B"})
control.register_nodes({"techage:ta4_solar_carrier"}, {
on_receive = function(pos, tlib2, topic, payload)
end,
on_request = function(pos, tlib2, topic)
if topic == "power" then
return on_getpower1(pos)
end
end,
}
)
control.register_nodes({"techage:ta4_solar_carrierB"}, {
on_receive = function(pos, tlib2, topic, payload)
end,
on_request = function(pos, tlib2, topic)
if topic == "power" then
return on_getpower2(pos)
end
end,
}
)
minetest.register_craft({
output = "techage:ta4_solar_module",
@ -288,13 +292,3 @@ minetest.register_craft({
},
})
--minetest.register_lbm({
-- label = "Repair Carrier Module",
-- name = "techage:ta4_solar_carrier",
-- nodenames = {"techage:ta4_solar_carrier", "techage:ta4_solar_carrierB"},
-- run_at_every_load = false,
-- action = function(pos, node)
-- local ndef = minetest.registered_nodes[node.name]
-- ndef.after_place_node(pos)
-- end,
--})

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -19,11 +19,10 @@ local S = techage.S
local STANDBY_TICKS = 4
local COUNTDOWN_TICKS = 4
local CYCLE_TIME = 2
local PWR_CAPA = 25
local PWR_PERF = 25
local Axle = techage.Axle
local power = techage.power
local networks = techage.networks
local power = networks.power
-- Axles texture animation
local function switch_axles(pos, on)
@ -32,15 +31,7 @@ local function switch_axles(pos, on)
end
local function formspec(self, pos, nvm)
return "size[4,4]"..
"box[0,-0.1;3.8,0.5;#c6e8ff]"..
"label[1,-0.1;"..minetest.colorize( "#000000", S("Flywheel")).."]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
power.formspec_label_bar(pos, 0, 0.8, S("power"), PWR_CAPA, nvm.provided)..
"image_button[2.8,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
"tooltip[2.8,2;1,1;"..self:get_state_tooltip(nvm).."]"
return techage.generator_formspec(self, pos, nvm, S("Flywheel"), nvm.provided, PWR_PERF, true)
end
local function transfer_cylinder(pos, topic, payload)
@ -55,18 +46,16 @@ end
local function start_node(pos, nvm, state)
switch_axles(pos, true)
local outdir = M(pos):get_int("outdir")
power.generator_start(pos, Axle, CYCLE_TIME, outdir)
transfer_cylinder(pos, "start")
nvm.running = true
power.start_storage_calc(pos, Axle, outdir)
end
local function stop_node(pos, nvm, state)
switch_axles(pos, false)
local outdir = M(pos):get_int("outdir")
power.generator_stop(pos, Axle, outdir)
nvm.provided = 0
transfer_cylinder(pos, "stop")
nvm.running = false
power.start_storage_calc(pos, Axle, outdir)
end
local State = techage.NodeStates:new({
@ -83,13 +72,20 @@ local State = techage.NodeStates:new({
local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos)
nvm.firebox_trigger = (nvm.firebox_trigger or 0) - 1
if nvm.firebox_trigger <= 0 then
State:nopower(pos, nvm)
local running = techage.is_running(nvm)
if running and nvm.firebox_trigger <= 0 then
State:standby(pos, nvm)
stop_node(pos, nvm, State)
transfer_cylinder(pos, "stop")
else
elseif not running and nvm.firebox_trigger > 0 then
State:start(pos, nvm)
-- start_node() is called implicit
elseif running then
local outdir = M(pos):get_int("outdir")
nvm.provided = power.generator_alive(pos, Axle, CYCLE_TIME, outdir)
nvm.provided = power.provide_power(pos, Axle, outdir, PWR_PERF)
local val = power.get_storage_load(pos, Axle, outdir, PWR_PERF)
if val > 0 then
nvm.load = val
end
State:keep_running(pos, nvm, COUNTDOWN_TICKS)
end
if techage.is_activeformspec(pos) then
@ -125,18 +121,13 @@ local function after_dig_node(pos, oldnode)
techage.del_mem(pos)
end
local function tubelib2_on_update2(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
local function get_generator_data(pos, outdir, tlib2)
local nvm = techage.get_nvm(pos)
if techage.is_running(nvm) then
return {level = (nvm.load or 0) / PWR_PERF, perf = PWR_PERF, capa = PWR_PERF * 4}
end
end
local net_def = {
axle = {
sides = {R = 1},
ntype = "gen1",
nominal = PWR_CAPA,
},
}
minetest.register_node("techage:flywheel", {
description = S("TA2 Flywheel"),
tiles = {
@ -154,8 +145,7 @@ minetest.register_node("techage:flywheel", {
on_timer = node_timer,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
get_generator_data = get_generator_data,
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
@ -208,8 +198,7 @@ minetest.register_node("techage:flywheel_on", {
on_timer = node_timer,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
get_generator_data = get_generator_data,
drop = "",
paramtype2 = "facedir",
@ -220,22 +209,21 @@ minetest.register_node("techage:flywheel_on", {
sounds = default.node_sound_wood_defaults(),
})
Axle:add_secondary_node_names({"techage:flywheel", "techage:flywheel_on"})
power.register_nodes({"techage:flywheel", "techage:flywheel_on"}, Axle, "gen", {"R"})
techage.register_node({"techage:flywheel", "techage:flywheel_on"}, {
on_transfer = function(pos, in_dir, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "trigger" then
nvm.firebox_trigger = 3
if nvm.running then
return math.max((nvm.provided or PWR_CAPA) / PWR_CAPA, 0.1)
if techage.is_running(nvm) then
return math.max((nvm.provided or PWR_PERF) / PWR_PERF, 0.1)
else
return 0
end
end
end,
on_node_load = function(pos, node)
M(pos):set_int("outdir", networks.side_to_outdir(pos, "R"))
State:on_node_load(pos)
end,
})

View File

@ -0,0 +1,85 @@
--[[
TechAge
=======
Copyright (C) 2019-2021 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
Rope for TA2 gravity-based energy storage
]]--
local Entities = {}
-- Return first pos after start pos and the destination pos
local function get_positions(pos, length, force)
local pos1 = {x = pos.x, y = pos.y - 1, z = pos.z} -- start pos
local pos2 = {x = pos.x, y = pos.y - 1 - length, z = pos.z} -- end pos
if force then
return pos1, pos2 -- force given length
end
local _, pos3 = minetest.line_of_sight(pos1, pos2)
return pos1, pos3 or pos2 -- new values
end
local function del_rope(pos)
local key = minetest.hash_node_position(pos)
local rope = Entities[key]
if rope then
rope:remove()
Entities[key] = nil
end
return key
end
local function add_rope(pos, pos1, pos2)
local key = del_rope(pos)
pos1.y = pos1.y + 0.5 -- from
pos2.y = pos2.y - 0.5 -- to
local pos3 = {x = pos1.x, y = (pos1.y + pos2.y) / 2, z = pos1.z} -- mid-pos
local length = math.abs(pos1.y - pos2.y)
local rope = minetest.add_entity(pos3, "techage:ta2_rope")
if rope then
rope:set_properties({visual_size = {x = 0.06, y = length}, collisionbox = {x = 0.06, y = length}})
end
Entities[key] = rope
end
minetest.register_entity("techage:ta2_rope", {
initial_properties = {
visual = "cube",
textures = {
"techage_rope.png",
"techage_rope.png",
"techage_rope.png",
"techage_rope.png",
"techage_rope.png",
"techage_rope.png",
},
use_texture_alpha = false,
physical = true,
collide_with_objects = true,
pointable = true,
static_save = false,
visual_size = {x = 0.06, y = 10, z = 0.06},
shaded = true,
},
})
-------------------------------------------------------------------------------
-- API functions
-------------------------------------------------------------------------------
function techage.renew_rope(pos, length, force)
local pos1, pos2 = get_positions(pos, length, force)
if pos1 then
add_rope(pos, pos1, pos2)
return pos1, pos2
end
end
techage.del_rope = del_rope

View File

@ -0,0 +1,138 @@
--[[
TechAge
=======
Copyright (C) 2019-2021 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
Chest for TA2 gravity-based energy storage
]]--
-- for lazy programmers
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local S2P = minetest.string_to_pos
local M = minetest.get_meta
local S = techage.S
local function valid_weight_items(stack)
local name = stack:get_name()
local ndef = minetest.registered_nodes[name]
if ndef then
if minetest.get_item_group(name, "stone") > 0 then
return true
end
if minetest.get_item_group(name, "cobble") > 0 then
return true
end
if minetest.get_item_group(name, "gravel") > 0 then
return true
end
if minetest.get_item_group(name, "sand") > 0 then
return true
end
end
end
minetest.register_entity("techage:ta2_weight_chest_entity", {
initial_properties = {
physical = true,
pointable = false,
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
visual = "wielditem",
textures = {"techage:ta2_weight_chest"},
visual_size = {x=0.66, y=0.66, z=0.66},
static_save = false,
},
})
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
if not valid_weight_items(stack) then
return 0
end
return stack:get_count()
end
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
return stack:get_count()
end
local function can_dig(pos, player)
if minetest.is_protected(pos, player:get_player_name()) then
return false
end
local inv = minetest.get_meta(pos):get_inventory()
return inv:is_empty("main")
end
local function after_dig_node(pos, oldnode, oldmetadata, digger)
techage.remove_node(pos, oldnode, oldmetadata)
end
local function formspec()
return "size[8,6.7]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"list[context;main;1.5,0.2;5,2;]"..
"list[current_player;main;0,3;8,4;]"..
"listring[context;main]"..
"listring[current_player;main]"
end
minetest.register_node("techage:ta2_weight_chest", {
description = S("TA2 Weight Chest"),
tiles = {
-- up, down, right, left, back, front
"techage_filling_ta2.png^techage_frame_ta2.png^techage_weight_bottom.png",
"techage_filling_ta2.png^techage_frame_ta2.png^techage_weight_bottom.png",
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png^techage_weight_side.png",
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png^techage_weight_side.png",
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png^techage_weight_side.png",
"techage_filling_ta2.png^techage_frame_ta2.png^techage_appl_chest_back_ta3.png^techage_weight_side.png",
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size('main', 10)
end,
after_place_node = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", formspec())
end,
techage_set_numbers = function(pos, numbers, player_name)
return techage.logic.set_numbers(pos, numbers, player_name, S("TA2 Weight Chest"))
end,
can_dig = can_dig,
after_dig_node = after_dig_node,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_craft({
output = "techage:ta2_weight_chest",
recipe = {
{"", "", ""},
{"basic_materials:steel_strip", "techage:chest_ta2", "basic_materials:steel_strip"},
{"", "", ""},
},
})

Some files were not shown because too many files have changed in this diff Show More