complete restructured

This commit is contained in:
Joachim Stolberg 2020-01-25 23:22:06 +01:00
parent 05f0fe64bd
commit eb77e68991
15 changed files with 2590 additions and 0 deletions

276
basic_machines/consumer.lua Normal file
View File

@ -0,0 +1,276 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
Consumer node basis functionality.
It handles:
- up to 3 stages of nodes (TA2/TA3/TA4)
- power consumption
- node state handling
- registration of passive and active nodes
- Tube connections are on left and right side (from left to right)
- Power connection are on front and back side (front or back)
]]--
-- 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
-- Consumer Related Data
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 function has_power(pos, nvm, state)
local crd = CRD(pos)
return power.power_available(pos, crd.power_netw)
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 crd = CRD(pos)
local nvm = techage.get_nvm(pos)
if crd.power_netw then
power.consumer_alive(pos, crd.power_netw, crd.cycle_time)
end
-- call the node timer routine
if techage.is_operational(nvm) then
crd.node_timer(pos, crd.cycle_time)
end
return crd.State:is_active(nvm)
end
local function prepare_tiles(tiles, stage, power_png)
local tbl = {}
for _,item in ipairs(tiles) do
if type(item) == "string" then
tbl[#tbl+1] = item:gsub("#", stage):gsub("{power}", power_png)
else
local temp = table.copy(item)
temp.image = temp.image:gsub("#", stage):gsub("{power}", power_png)
tbl[#tbl+1] = temp
end
end
return tbl
end
-- 'validStates' is optional and can be used to e.g. enable
-- only one TA2 node {false, true, false, false}
function techage.register_consumer(base_name, inv_name, tiles, tNode, validStates)
local names = {}
validStates = validStates or {true, true, true, true}
for stage = 2,4 do
local name_pas = "techage:ta"..stage.."_"..base_name.."_pas"
local name_act = "techage:ta"..stage.."_"..base_name.."_act"
local name_inv = "TA"..stage.." "..inv_name
names[#names+1] = name_pas
if validStates[stage] then
local on_recv_message = tNode.tubing.on_recv_message
if stage > 2 then
on_recv_message = function(pos, src, topic, payload)
return "unsupported"
end
end
local power_network
local power_png = 'techage_axle_clutch.png'
local power_used = tNode.power_consumption ~= nil
local tNetworks
-- 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},
ntype = "con1",
nominal = tNode.power_consumption[stage],
on_power = on_power,
on_nopower = on_nopower,
},
}
else
power_network = techage.Axle
power_png = 'techage_axle_clutch.png'
tNetworks = {
axle = {
sides = tNode.power_sides or {F=1, B=1},
ntype = "con1",
nominal = tNode.power_consumption[stage],
on_power = on_power,
on_nopower = on_nopower,
}
}
end
end
local tState = techage.NodeStates:new({
node_name_passive = name_pas,
node_name_active = name_act,
infotext_name = name_inv,
cycle_time = tNode.cycle_time,
standby_ticks = tNode.standby_ticks,
formspec_func = tNode.formspec,
on_state_change = tNode.on_state_change,
can_start = tNode.can_start,
has_power = tNode.has_power or power_used and has_power or nil,
start_node = power_used and start_node or nil,
stop_node = power_used and stop_node or nil,
})
local tConsumer = {
stage = stage,
State = tState,
-- number of items to be processed per cycle
num_items = tNode.num_items and tNode.num_items[stage],
power_consumption = power_used and
tNode.power_consumption[stage] or 0,
node_timer = tNode.node_timer,
cycle_time = tNode.cycle_time,
power_netw = power_network,
}
local after_place_node = function(pos, placer, itemstack, pointed_thing)
local crd = CRD(pos)
local meta = M(pos)
local nvm = techage.get_nvm(pos)
local node = minetest.get_node(pos)
meta:set_int("push_dir", techage.side_to_indir("L", node.param2))
meta:set_int("pull_dir", techage.side_to_indir("R", node.param2))
local number = "-"
if stage > 2 then
number = techage.add_node(pos, name_pas)
end
if crd.power_netw then
crd.power_netw:after_place_node(pos)
end
if tNode.after_place_node then
tNode.after_place_node(pos, placer, itemstack, pointed_thing)
end
crd.State:node_init(pos, nvm, number)
end
local after_dig_node = function(pos, oldnode, oldmetadata, digger)
if tNode.after_dig_node then
tNode.after_dig_node(pos, oldnode, oldmetadata, digger)
end
local crd = CRDN(oldnode)
if crd.power_netw then
crd.power_netw:after_dig_node(pos)
end
techage.remove_node(pos)
techage.del_mem(pos)
end
local tubelib2_on_update2 = function(pos, outdir, tlib2, node)
power.update_network(pos, outdir, tlib2)
end
tNode.groups.not_in_creative_inventory = 0
minetest.register_node(name_pas, {
description = name_inv,
tiles = prepare_tiles(tiles.pas, stage, power_png),
consumer = tConsumer,
drawtype = tNode.drawtype,
node_box = tNode.node_box,
selection_box = tNode.selection_box,
can_dig = tNode.can_dig,
on_rotate = screwdriver.disallow,
on_timer = node_timer,
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",
groups = table.copy(tNode.groups),
is_ground_content = false,
sounds = tNode.sounds,
})
tNode.groups.not_in_creative_inventory = 1
minetest.register_node(name_act, {
description = name_inv,
tiles = prepare_tiles(tiles.act, stage, power_png),
consumer = tConsumer,
drawtype = tNode.drawtype,
node_box = tNode.node_box,
selection_box = tNode.selection_box,
on_rotate = screwdriver.disallow,
on_timer = node_timer,
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",
drop = "",
diggable = false,
groups = table.copy(tNode.groups),
is_ground_content = false,
sounds = tNode.sounds,
})
if power_used then
power_network:add_secondary_node_names({name_pas, name_act})
end
techage.register_node({name_pas, name_act}, tNode.tubing)
end
end
return names[1], names[2], names[3]
end

122
basis/boiler_lib.lua Normal file
View File

@ -0,0 +1,122 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
Boiler common functions
]]--
-- for lazy programmers
local P = minetest.string_to_pos
local M = minetest.get_meta
local S = techage.S
local HEAT_STEP = 10
local MAX_WATER = 10
local BLOCKING_TIME = 0.3 -- 300ms
techage.boiler = {}
local IsWater = {
["bucket:bucket_river_water"] = true,
["bucket:bucket_water"] = true,
}
local IsBucket = {
["bucket:bucket_empty"] = true,
}
local function node_description(name)
name = string.split(name, " ")[1]
local ndef = minetest.registered_nodes[name] or minetest.registered_items[name] or minetest.registered_craftitems[name]
if ndef and ndef.description then
return minetest.formspec_escape(ndef.description)
end
return ""
end
local function item_image(x, y, itemname)
return "box["..x..","..y..";0.85,0.9;#808080]"..
"item_image["..x..","..y..";1,1;"..itemname.."]"
end
function techage.boiler.formspec(pos, nvm)
local title = S("Water Boiler")
local temp = nvm.temperature or 20
local ratio = nvm.power_ratio or 0
local tooltip = S("To add water punch\nthe boiler\nwith a water bucket")
return "size[5,3]"..
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", title).."]"..
item_image(1, 1.5, "default:water_source "..(nvm.num_water or 0))..
"tooltip[1,1.5;1,1;"..tooltip..";#0C3D32;#FFFFFF]"..
"image[3,1.0;1,2;techage_form_temp_bg.png^[lowpart:"..
temp..":techage_form_temp_fg.png]"..
"tooltip[3,1;1,2;"..S("water temperature")..";#0C3D32;#FFFFFF]"
end
function techage.boiler.water_temperature(pos, nvm)
nvm.temperature = nvm.temperature or 20
nvm.num_water = nvm.num_water or 0
if nvm.fire_trigger then
nvm.temperature = math.min(nvm.temperature + HEAT_STEP, 100)
else
nvm.temperature = math.max(nvm.temperature - HEAT_STEP, 20)
end
nvm.fire_trigger = false
if nvm.water_level == 0 then
if nvm.num_water > 0 then
nvm.num_water = nvm.num_water - 1
nvm.water_level = 100
else
nvm.temperature = 20
end
end
return nvm.temperature
end
function techage.boiler.on_rightclick(pos, node, clicker)
techage.set_activeformspec(pos, clicker)
local nvm = techage.get_nvm(pos)
M(pos):set_string("formspec", techage.boiler.formspec(pos, nvm))
end
function techage.boiler.can_dig(pos, player)
local nvm = techage.get_nvm(pos)
nvm.num_water = nvm.num_water or 0
return nvm.num_water == 0
end
function techage.boiler.on_punch(pos, node, puncher, pointed_thing)
local nvm = techage.get_nvm(pos)
local mem = techage.get_mem(pos)
mem.blocking_time = mem.blocking_time or 0
if mem.blocking_time > techage.SystemTime then
return
end
nvm.num_water = nvm.num_water or 0
local wielded_item = puncher:get_wielded_item():get_name()
if IsWater[wielded_item] and nvm.num_water < MAX_WATER then
mem.blocking_time = techage.SystemTime + BLOCKING_TIME
nvm.num_water = nvm.num_water + 1
puncher:set_wielded_item(ItemStack("bucket:bucket_empty"))
M(pos):set_string("formspec", techage.boiler.formspec(pos, nvm))
elseif IsBucket[wielded_item] and nvm.num_water > 0 then
mem.blocking_time = techage.SystemTime + BLOCKING_TIME
nvm.num_water = nvm.num_water - 1
puncher:set_wielded_item(ItemStack("bucket:bucket_water"))
M(pos):set_string("formspec", techage.boiler.formspec(pos, nvm))
end
end

42
basis/formspec_update.lua Normal file
View File

@ -0,0 +1,42 @@
--[[
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
Keep only one formspec active per player
]]--
local P2S = minetest.pos_to_string
local ActiveFormspecs = {}
local ActivePlayer = {}
function techage.is_activeformspec(pos)
return ActiveFormspecs[P2S(pos)]
end
function techage.set_activeformspec(pos, player)
local name = player and player:get_player_name()
if name then
if ActivePlayer[name] then
ActiveFormspecs[ActivePlayer[name]] = nil
end
ActivePlayer[name] = P2S(pos)
ActiveFormspecs[P2S(pos)] = true
end
end
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
if ActivePlayer[name] then
ActiveFormspecs[ActivePlayer[name]] = nil
ActivePlayer[name] = nil
end
end)

126
basis/storage.lua Normal file
View File

@ -0,0 +1,126 @@
--[[
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
Memory storage system for volatile and non-volatile memory.
Non-volatile memory is stored from time to time and at shutdown
as node metadata. Volatile memory is lost at every shutdown.
]]--
local NUM_NODES_PER_MIN = 100
local NvmStore = {}
local MemStore = {}
local NumNodes = 0
local StoredNodes = 0
local function set_metadata(hash, tbl)
local pos = minetest.get_position_from_hash(hash)
local data = minetest.serialize(tbl)
local meta = minetest.get_meta(pos)
meta:set_string("ta_data", data)
meta:mark_as_private("ta_data")
end
local function get_metadata(hash)
local pos = minetest.get_position_from_hash(hash)
local meta = minetest.get_meta(pos)
local s = meta:get_string("ta_data")
if s ~= "" then
return minetest.deserialize(s)
end
end
local function storage_loop()
local cnt = 0
while true do
NumNodes = 0
StoredNodes = 0
for hash,tbl in pairs(NvmStore) do
NumNodes = NumNodes + 1
if tbl.__used__ then
tbl.__used__ = nil
set_metadata(hash, tbl)
StoredNodes = StoredNodes + 1
cnt = cnt + 1
if cnt > NUM_NODES_PER_MIN then
cnt = 0
coroutine.yield()
end
else
-- remove from memory if node is unloaded
local pos = minetest.get_position_from_hash(hash)
if minetest.get_node(pos).name == "ignore" then
NvmStore[hash] = nil
MemStore[hash] = nil
end
end
end
coroutine.yield()
end
end
local co = coroutine.create(storage_loop)
local function cyclic_task()
local t = minetest.get_us_time()
coroutine.resume(co)
t = minetest.get_us_time() - t
print("[TA NVM Storage] duration="..t.."us, total="..NumNodes..", stored="..StoredNodes)
-- run every minutes
minetest.after(60, cyclic_task)
end
minetest.register_on_shutdown(function()
NumNodes = 0
StoredNodes = 0
local t = minetest.get_us_time()
for k,v in pairs(NvmStore) do
NumNodes = NumNodes + 1
if v.__used__ then
v.__used__ = nil
set_metadata(k, v)
StoredNodes = StoredNodes + 1
end
end
t = minetest.get_us_time() - t
print("[TA NVM Storage] duration="..t.."us, total="..NumNodes..", stored="..StoredNodes)
end)
minetest.after(60, cyclic_task)
-- To get the volatile node data as table
function techage.get_mem(pos, will_change)
local hash = minetest.hash_node_position(pos)
if not MemStore[hash] then
MemStore[hash] = {}
end
return MemStore[hash]
end
-- To get the nonvolatile node data as table
function techage.get_nvm(pos)
local hash = minetest.hash_node_position(pos)
if not NvmStore[hash] then
NvmStore[hash] = get_metadata(hash) or {}
end
NvmStore[hash].__used__ = true
return NvmStore[hash]
end
-- To be called when a node is removed
function techage.del_mem(pos)
local meta = minetest.get_meta(pos)
meta:set_string("ta_data", "")
local hash = minetest.hash_node_position(pos)
NvmStore[hash] = nil
MemStore[hash] = nil
end

View File

@ -0,0 +1,398 @@
--[[
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
TA3 Coal Power Station Firebox
]]--
-- for lazy programmers
local P = minetest.string_to_pos
local M = minetest.get_meta
local S = techage.S
local firebox = techage.firebox
local fuel = techage.fuel
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local CYCLE_TIME = 2
local EFFICIENCY = 0.5
local function firehole(pos, on)
local param2 = techage.get_node_lvm(pos).param2
local pos2 = techage.get_pos(pos, 'F')
if on == true then
minetest.swap_node(pos2, {name="techage:coalfirehole_on", param2 = param2})
elseif on == false then
minetest.swap_node(pos2, {name="techage:coalfirehole", param2 = param2})
else
minetest.swap_node(pos2, {name="air"})
end
end
local function node_timer(pos, elapsed)
local mem = tubelib2.get_mem(pos)
if mem.running then
-- trigger generator and provide power ratio 0..1
local ratio = techage.transfer(
{x=pos.x, y=pos.y+2, z=pos.z},
nil, -- outdir
"trigger", -- topic
(mem.power_level or 4)/4.0, -- payload
nil, -- network
{"techage:coalboiler_top"} -- nodenames
)
ratio = math.max((ratio or 0.02), 0.02)
mem.burn_cycles = (mem.burn_cycles or 0) - ratio
if mem.burn_cycles <= 0 then
local taken = firebox.get_fuel(pos)
if taken then
mem.burn_cycles = (firebox.Burntime[taken:get_name()] or 1) * EFFICIENCY / CYCLE_TIME
mem.burn_cycles_total = mem.burn_cycles
else
mem.running = false
firehole(pos, false)
M(pos):set_string("formspec", firebox.formspec(mem))
return false
end
end
return true
end
end
local function start_firebox(pos, mem)
if not mem.running then
mem.running = true
node_timer(pos, 0)
firehole(pos, true)
minetest.get_node_timer(pos):start(CYCLE_TIME)
end
end
minetest.register_node("techage:coalfirebox", {
description = S("TA3 Power Station Firebox"),
inventory_image = "techage_coal_boiler_inv.png",
tiles = {"techage_coal_boiler_mesh_top.png"},
drawtype = "mesh",
mesh = "techage_cylinder_12.obj",
selection_box = {
type = "fixed",
fixed = {-13/32, -16/32, -13/32, 13/32, 16/32, 13/32},
},
paramtype = "light",
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
groups = {cracky=2},
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_timer = node_timer,
can_dig = firebox.can_dig,
allow_metadata_inventory_put = firebox.allow_metadata_inventory_put,
allow_metadata_inventory_take = firebox.allow_metadata_inventory_take,
on_receive_fields = firebox.on_receive_fields,
on_rightclick = firebox.on_rightclick,
on_construct = function(pos)
local mem = tubelib2.init_mem(pos)
techage.add_node(pos, "techage:coalfirebox")
mem.running = false
mem.burn_cycles = 0
mem.power_level = 4
local meta = M(pos)
meta:set_string("formspec", firebox.formspec(mem))
local inv = meta:get_inventory()
inv:set_size('fuel', 1)
firehole(pos, false)
end,
on_destruct = function(pos)
firehole(pos, nil)
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
local mem = tubelib2.get_mem(pos)
start_firebox(pos, mem)
M(pos):set_string("formspec", firebox.formspec(mem))
end,
})
minetest.register_node("techage:coalfirehole", {
description = S("TA3 Coal Power Station Firebox"),
tiles = {
-- up, down, right, left, back, front
"techage_coal_boiler.png",
"techage_coal_boiler.png",
"techage_coal_boiler.png",
"techage_coal_boiler.png",
"techage_coal_boiler.png",
"techage_coal_boiler.png^techage_appl_firehole.png",
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-6/16, -6/16, 6/16, 6/16, 6/16, 12/16},
},
},
paramtype = "light",
paramtype2 = "facedir",
pointable = false,
diggable = false,
is_ground_content = false,
groups = {not_in_creative_inventory=1},
})
minetest.register_node("techage:coalfirehole_on", {
description = S("TA3 Coal Power Station Firebox"),
tiles = {
-- up, down, right, left, back, front
"techage_coal_boiler.png^[colorize:black:80",
"techage_coal_boiler.png^[colorize:black:80",
"techage_coal_boiler.png^[colorize:black:80",
"techage_coal_boiler.png^[colorize:black:80",
"techage_coal_boiler.png^[colorize:black:80",
{
image = "techage_coal_boiler4.png^[colorize:black:80^techage_appl_firehole4.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 0.4,
},
},
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{-6/16, -6/16, 6/16, 6/16, 6/16, 12/16},
},
},
paramtype = "light",
paramtype2 = "facedir",
light_source = 8,
pointable = false,
diggable = false,
is_ground_content = false,
groups = {not_in_creative_inventory=1},
})
local function on_timer2(pos, elapsed)
local mem = tubelib2.get_mem(pos)
if mem.running then
fuel.formspec_update(pos, mem)
-- trigger generator and provide power ratio 0..1
local ratio = techage.transfer(
{x=pos.x, y=pos.y+2, z=pos.z},
nil, -- outdir
"trigger", -- topic
(mem.power_level or 4)/4.0, -- payload
nil, -- network
{"techage:coalboiler_top"} -- nodenames
)
ratio = math.max((ratio or 0.02), 0.02)
mem.burn_cycles = (mem.burn_cycles or 0) - ratio
mem.liquid = mem.liquid or {}
mem.liquid.amount = mem.liquid.amount or 0
if mem.burn_cycles <= 0 then
if mem.liquid.amount > 0 then
mem.liquid.amount = mem.liquid.amount - 1
mem.burn_cycles = fuel.burntime(mem.liquid.name) * EFFICIENCY / CYCLE_TIME
mem.burn_cycles_total = mem.burn_cycles
else
mem.running = false
mem.liquid.name = nil
firehole(pos, false)
M(pos):set_string("formspec", fuel.formspec(mem))
return false
end
end
return true
end
end
local function start_firebox2(pos, mem)
if not mem.running and mem.liquid.amount > 0 then
mem.running = true
on_timer2(pos, 0)
firehole(pos, true)
minetest.get_node_timer(pos):start(CYCLE_TIME)
M(pos):set_string("formspec", fuel.formspec(mem))
end
end
minetest.register_node("techage:oilfirebox", {
description = S("TA3 Power Station Oil Burner"),
inventory_image = "techage_oil_boiler_inv.png",
tiles = {"techage_coal_boiler_mesh_top.png"},
drawtype = "mesh",
mesh = "techage_cylinder_12.obj",
selection_box = {
type = "fixed",
fixed = {-13/32, -16/32, -13/32, 13/32, 16/32, 13/32},
},
paramtype = "light",
paramtype2 = "facedir",
on_rotate = screwdriver.disallow,
groups = {cracky=2},
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_timer = on_timer2,
can_dig = fuel.can_dig,
allow_metadata_inventory_take = fuel.allow_metadata_inventory_take,
allow_metadata_inventory_put = fuel.allow_metadata_inventory_put,
on_receive_fields = fuel.on_receive_fields,
on_rightclick = fuel.on_rightclick,
on_construct = function(pos)
local mem = tubelib2.init_mem(pos)
techage.add_node(pos, "techage:oilfirebox")
mem.running = false
mem.burn_cycles = 0
mem.liquid = {}
mem.liquid.amount = 0
local meta = M(pos)
meta:set_string("formspec", fuel.formspec(mem))
local inv = meta:get_inventory()
inv:set_size('fuel', 1)
firehole(pos, false)
end,
on_destruct = function(pos)
firehole(pos, nil)
end,
on_metadata_inventory_put = function(pos, listname, index, stack, player)
local mem = tubelib2.get_mem(pos)
mem.liquid = mem.liquid or {}
mem.liquid.amount = mem.liquid.amount or 0
minetest.after(1, start_firebox2, pos, mem)
fuel.on_metadata_inventory_put(pos, listname, index, stack, player)
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 mem = tubelib2.get_mem(pos)
mem.liquid = mem.liquid or {}
mem.liquid.amount = mem.liquid.amount or 0
start_firebox2(pos, mem)
return leftover
end
return amount
end,
take = liquid.srv_take,
},
networks = {
pipe = {
sides = techage.networks.AllSides, -- Pipe connection sides
ntype = "tank",
},
},
})
Pipe:add_secondary_node_names({"techage:oilfirebox"})
techage.register_node({"techage:coalfirebox"}, {
on_pull_item = function(pos, in_dir, num)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return techage.get_items(inv, "fuel", num)
end,
on_push_item = function(pos, in_dir, stack)
if firebox.Burntime[stack:get_name()] then
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local mem = tubelib2.get_mem(pos)
start_firebox(pos, mem)
return techage.put_items(inv, "fuel", stack)
end
return false
end,
on_unpull_item = function(pos, in_dir, stack)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return techage.put_items(inv, "fuel", stack)
end,
on_recv_message = function(pos, src, topic, payload)
local mem = tubelib2.get_mem(pos)
if topic == "state" then
if mem.running then
return "running"
else
return "stopped"
end
elseif topic == "fuel" then
local inv = M(pos):get_inventory()
local stack = inv:get_stack("fuel", 1)
return stack:get_count()
else
return "unsupported"
end
end,
})
techage.register_node({"techage:oilfirebox"}, {
on_recv_message = function(pos, src, topic, payload)
local mem = tubelib2.get_mem(pos)
if topic == "state" then
if mem.running then
return "running"
else
return "stopped"
end
elseif topic == "fuel" then
return mem.liquid and mem.liquid.amount and mem.liquid.amount
else
return "unsupported"
end
end,
})
minetest.register_craft({
output = "techage:coalfirebox",
recipe = {
{'default:stone', 'default:stone', 'default:stone'},
{'default:steel_ingot', '', 'default:steel_ingot'},
{'default:stone', 'default:stone', 'default:stone'},
},
})
minetest.register_craft({
output = "techage:oilfirebox",
recipe = {
{'', 'techage:coalfirebox', ''},
{'', 'techage:ta3_barrel_empty', ''},
{'', '', ''},
},
})
minetest.register_lbm({
label = "[techage] Power Station firebox",
name = "techage:steam_engine",
nodenames = {"techage:coalfirebox", "techage:oilfirebox"},
run_at_every_load = true,
action = function(pos, node)
minetest.get_node_timer(pos):start(CYCLE_TIME)
end
})

View File

@ -0,0 +1,29 @@
--[[
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
TA4 Hydrogen
]]--
local S = techage.S
minetest.register_craftitem("techage:ta4_fuelcellstack", {
description = S("TA4 Fuel Cell Stack"),
inventory_image = "techage_fc_stack_inv.png",
})
minetest.register_craft({
output = "techage:ta4_fuelcellstack",
recipe = {
{'techage:baborium_ingot', 'techage:ta4_carbon_fiber', 'default:copper_ingot'},
{'default:gold_ingot', 'techage:ta4_carbon_fiber', 'default:tin_ingot'},
{"techage:baborium_ingot", 'techage:ta4_carbon_fiber', 'default:copper_ingot'},
},
})

142
liquids/liquid_lib.lua Normal file
View File

@ -0,0 +1,142 @@
--[[
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
Liquid lib
]]--
local M = minetest.get_meta
local S = techage.S
local liquid = techage.liquid
local LQD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).liquid end
function techage.liquid.formspec_liquid(x, y, mem)
local itemname = "techage:liquid"
if mem.liquid and mem.liquid.amount and mem.liquid.amount > 0 and mem.liquid.name then
itemname = mem.liquid.name.." "..mem.liquid.amount
end
return "container["..x..","..y.."]"..
"background[0,0;3,2.05;techage_form_grey.png]"..
"image[0,0;1,1;techage_form_input_arrow.png]"..
techage.item_image(1, 0, itemname)..
"image[2,0;1,1;techage_form_output_arrow.png]"..
"image[1,1;1,1;techage_form_arrow.png]"..
"list[context;src;0,1;1,1;]"..
"list[context;dst;2,1;1,1;]"..
"listring[current_player;main]"..
"listring[context;src]" ..
"listring[current_player;main]"..
"listring[context;dst]" ..
"listring[current_player;main]"..
"container_end[]"
end
local function fill_container(pos, inv)
local mem = tubelib2.get_mem(pos)
mem.liquid = mem.liquid or {}
mem.liquid.amount = mem.liquid.amount or 0
local empty_container = inv:get_stack("src", 1):get_name()
local full_container = liquid.get_full_container(empty_container, mem.liquid.name)
if empty_container and full_container then
local ldef = liquid.get_liquid_def(full_container)
if ldef and mem.liquid.amount - ldef.size >= 0 then
if inv:room_for_item("dst", ItemStack(full_container)) then
inv:remove_item("src", ItemStack(empty_container))
inv:add_item("dst", ItemStack(full_container))
mem.liquid.amount = mem.liquid.amount - ldef.size
if mem.liquid.amount == 0 then
mem.liquid.name = nil
end
end
end
end
end
local function empty_container(pos, inv, size)
local mem = tubelib2.get_mem(pos)
mem.liquid = mem.liquid or {}
mem.liquid.amount = mem.liquid.amount or 0
local stack = inv:get_stack("src", 1)
local ldef = liquid.get_liquid_def(stack:get_name())
if ldef and (not mem.liquid.name or ldef.inv_item == mem.liquid.name) then
local amount = stack:get_count() * ldef.size
if mem.liquid.amount + amount <= size then
if inv:room_for_item("dst", ItemStack(ldef.container)) then
inv:remove_item("src", stack)
inv:add_item("dst", ItemStack(ldef.container))
mem.liquid.amount = mem.liquid.amount + amount
mem.liquid.name = ldef.inv_item
end
end
end
end
function techage.liquid.move_item(pos, stack, size, formspec)
local mem = tubelib2.get_mem(pos)
local inv = M(pos):get_inventory()
if liquid.is_container_empty(stack:get_name()) then
fill_container(pos, inv)
else
empty_container(pos, inv, size)
end
M(pos):set_string("formspec", formspec(pos, mem))
end
function techage.liquid.is_empty(pos)
local mem = tubelib2.get_mem(pos)
local inv = minetest.get_meta(pos):get_inventory()
return inv:is_empty("src") and inv:is_empty("dst") and (not mem.liquid or (mem.liquid.amount or 0) == 0)
end
techage.liquid.tubing = {
on_pull_item = function(pos, in_dir, num)
local inv = M(pos):get_inventory()
if not inv:is_empty("dst") then
local taken = techage.get_items(inv, "dst", num)
if not inv:is_empty("src") then
fill_container(pos, inv)
end
return taken
end
end,
on_push_item = function(pos, in_dir, stack)
local inv = M(pos):get_inventory()
if inv:room_for_item("src", stack) then
inv:add_item("src", stack)
if liquid.is_container_empty(stack:get_name()) then
fill_container(pos, inv)
else
empty_container(pos, inv)
end
return true
end
return false
end,
on_unpull_item = function(pos, in_dir, stack)
local meta = M(pos)
local inv = meta:get_inventory()
return techage.put_items(inv, "dst", stack)
end,
on_recv_message = function(pos, src, topic, payload)
if topic == "load" then
local mem = tubelib2.get_mem(pos)
return techage.power.percent(LQD(pos).capa, (mem.liquid and mem.liquid.amount) or 0)
elseif topic == "size" then
return LQD(pos).capa
else
return "unsupported"
end
end,
}
techage.liquid.fill_container = fill_container
techage.liquid.empty_container = empty_container

135
power/distribution.lua Normal file
View File

@ -0,0 +1,135 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
Power Distribution
]]--
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)
if nvm[tlib_type.."_cstate"] == NOPOWER and (nvm[tlib_type.."_calive"] or 0) > 0 then
local ndef = net_def(v.pos, tlib_type)
nvm[tlib_type.."_cstate"] = RUNNING
nvm[tlib_type.."_taken"] = v.nominal or 0
if ndef.on_power then
ndef.on_power(v.pos)
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)
if nvm[tlib_type.."_cstate"] == RUNNING then
local ndef = net_def(v.pos, tlib_type)
nvm[tlib_type.."_cstate"] = NOPOWER
nvm[tlib_type.."_taken"] = 0
if ndef.on_nopower then
ndef.on_nopower(v.pos)
end
end
end
end
local function get_generator_sum(tbl, tlib_type)
local sum = 0
for _,v in ipairs(tbl or {}) do
local nvm = techage.get_nvm(v.pos)
if nvm[tlib_type.."_gstate"] ~= STOPPED then
nvm[tlib_type.."_galive"] = (nvm[tlib_type.."_galive"] or 1) - 1
if nvm[tlib_type.."_galive"] > 0 then
sum = sum + v.nominal
end
end
end
return sum
end
local function get_consumer_sum(tbl, tlib_type)
local sum = 0
for _,v in ipairs(tbl or {}) do
local nvm = techage.get_nvm(v.pos)
if nvm[tlib_type.."_cstate"] ~= STOPPED then
nvm[tlib_type.."_calive"] = (nvm[tlib_type.."_calive"] or 1) - 1
if nvm[tlib_type.."_calive"] > 0 then
sum = sum + v.nominal
end
end
end
return sum
end
local function set_given(pos, given, tlib_type)
local nvm = techage.get_nvm(pos)
if (nvm[tlib_type.."_galive"] or 0) > 0 then
nvm[tlib_type.."_given"] = given
return given
end
return 0
end
local function set_taken(pos, taken, tlib_type)
local nvm = techage.get_nvm(pos)
if (nvm[tlib_type.."_calive"] or 0) > 0 then
nvm[tlib_type.."_taken"] = taken
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, t)
-- calc maximum power values
network.available1 = get_generator_sum(network.gen1, tlib_type)
network.available2 = get_generator_sum(network.gen2, tlib_type)
network.needed1 = get_consumer_sum(network.con1, tlib_type)
network.needed2 = get_consumer_sum(network.con2, tlib_type)
print(t, minetest.get_gametime(), 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

75
power/formspecs.lua Normal file
View File

@ -0,0 +1,75 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
Power Formspec Functions
]]--
--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
function techage.power.percent(max_val, curr_val)
return math.min(math.ceil(((curr_val or 0) * 100.0) / (max_val or 1.0)), 100)
end
function techage.power.formspec_load_bar(charging, max_val)
local percent
charging = charging or 0
max_val = max_val or 1
if charging ~= 0 then
percent = 50 + math.ceil((charging * 50.0) / max_val)
end
if charging > 0 then
return "techage_form_level_off.png^[lowpart:"..percent..":techage_form_level_charge.png"
elseif charging < 0 then
return "techage_form_level_unload.png^[lowpart:"..percent..":techage_form_level_off.png"
else
return "techage_form_level_off.png"
end
end
function techage.power.formspec_power_bar(max_power, current_power)
if (current_power or 0) == 0 then
return "techage_form_level_bg.png"
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"
end
function techage.power.formspec_label_bar(x, y, label, max_power, current_power)
local percent, ypos
current_power = current_power or 0
if current_power == 0 then
percent = 0
ypos = 2.8
else
percent = techage.power.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
percent = (percent + 5) / 1.1 -- texture correction
return "container["..x..","..y.."]"..
"box[0,0;2.3,3.3;#395c74]"..
"label[0.2,0;"..label.."]"..
"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]"..
"container_end[]"
end

151
power/gearbox.lua Normal file
View File

@ -0,0 +1,151 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
TA2 Gearbox
]]--
-- for lazy programmers
local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local PWR_NEEDED = 1
local CYCLE_TIME = 4
local Axle = techage.Axle
local power = techage.power
local networks = techage.networks
-- Axles texture animation
local function switch_axles(pos, on)
for _,outdir in ipairs(networks.get_node_connections(pos, "axle")) do
Axle:switch_tube_line(pos, outdir, on and "on" or "off")
end
end
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 on_power(pos)
swap_node(pos, "techage:gearbox_on")
switch_axles(pos, 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)
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)
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,
},
}
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,
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,
paramtype = "light",
light_source = 0,
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
on_rotate = screwdriver.disallow,
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("techage:gearbox_on", {
tiles = {
-- up, down, right, left, back, front
{
image = "techage_filling4_ta2.png^techage_axle_gearbox4.png^techage_frame4_ta2.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 0.6,
},
},
},
on_timer = node_timer,
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,
paramtype2 = "facedir",
groups = {not_in_creative_inventory=1},
diggable = false,
drop = "",
on_rotate = screwdriver.disallow,
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
Axle:add_secondary_node_names({"techage:gearbox", "techage:gearbox_on"})
minetest.register_craft({
output = "techage:gearbox 2",
recipe = {
{"default:junglewood", "techage:axle", "default:wood"},
{"techage:axle", "techage:iron_ingot", "techage:axle"},
{"default:wood", "techage:axle", "default:junglewood"},
},
})

186
power/node_api.lua Normal file
View File

@ -0,0 +1,186 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
GPL 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.."_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.."_netID"] then
netID = nvm[Cable.tube_type.."_netID"]
nvm[Cable.tube_type.."_netID"] = nil
end
end
end)
networks.delete_network(netID, Cable)
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.."_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.has_network(Cable.tube_type, netID) then
print("build_network !!!!!!!!!!!!!!!!!!!!")
networks.build_network(pos, outdir, 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
--
-- Consumer related functions
--
-- check if there is a living network
function techage.power.power_available(pos, Cable)
-- for _,outdir in ipairs(techage.networks.get_node_connections(pos, Cable.tube_type)) do
-- -- generator visible?
-- if determine_netID(pos, outdir, Cable) > 0 then return true end
-- end
local nvm = techage.get_nvm(pos)
local tlib_type = Cable.tube_type
return networks.has_network(tlib_type, nvm[tlib_type.."_netID"])
-- local mem = techage.get_mem(pos)
-- local tlib_type = Cable.tube_type
-- local netID = nvm[tlib_type.."_netID"]
-- local netw = techage.networks.get_network(tlib_type, netID)
-- if netw then -- network available
-- if not mem.new_ticker or mem.new_ticker ~= netw.ticker then
-- mem.new_ticker = netw.ticker
-- return true
-- end
-- return false
-- 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.."_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.."_calive"] = 0
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 tlib_type = Cable.tube_type
if nvm[tlib_type.."_netID"] then -- network available
nvm[tlib_type.."_calive"] = (cycle_time / 2) + 1
elseif nvm[tlib_type.."_cstate"] == RUNNING then
local ndef = net_def(pos, tlib_type)
ndef.on_nopower(pos)
nvm[tlib_type.."_cstate"] = NOPOWER
end
return nvm[tlib_type.."_taken"] or 0
end
--
-- Generator related functions
--
function techage.power.generator_start(pos, Cable, cycle_time, outdir)
local nvm = techage.get_nvm(pos)
local tlib_type = Cable.tube_type
nvm[tlib_type.."_galive"] = (cycle_time / 2) + 2
nvm[tlib_type.."_gstate"] = RUNNING
nvm[tlib_type.."_given"] = 0
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.."_galive"] = 0
nvm[tlib_type.."_gstate"] = STOPPED
nvm[tlib_type.."_given"] = 0
end
function techage.power.generator_alive(pos, Cable, cycle_time, outdir)
local nvm = techage.get_nvm(pos)
local tlib_type = Cable.tube_type
trigger_network(pos, outdir, Cable)
nvm[tlib_type.."_galive"] = (cycle_time / 2) + 2
return nvm[tlib_type.."_given"] or 0
end
-- function delete_netID(pos, outdir, Cable)
techage.power.delete_netID = delete_netID

220
power/power_terminal.lua Normal file
View File

@ -0,0 +1,220 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
TA3 Power Terminal
]]--
-- 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_gstate and nvm.ele1_gstate ~= STOPPED then
tbl.num_on = tbl.num_on + 1
tbl.pow_on = tbl.pow_on + (gen.nominal or 0)
if (nvm.ele1_galive or 0) > 0 then
tbl.num_act = tbl.num_act + 1
tbl.pow_act = tbl.pow_act + (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_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 0) > 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_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(0, 0.7, S("Genera. 1"), gen1.pow_act, gen1.pow_used)..
power.formspec_label_bar(2.5, 0.7, S("Genera. 2"), gen2.pow_act, gen2.pow_used)..
power.formspec_label_bar(5, 0.7, S("Consum. 2"), con2.pow_act, con2.pow_used)..
power.formspec_label_bar(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"),
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",
on_rotate = screwdriver.disallow,
sunlight_propagates = true,
is_ground_content = false,
groups = {cracky = 1, level = 2},
sounds = default.node_sound_metal_defaults(),
})
Cable:add_secondary_node_names({"techage:power_terminal"})

183
power/powerswitchbox.lua Normal file
View File

@ -0,0 +1,183 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
TA3 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 = techage.power
local networks = techage.networks
-- simpe rotation of a facedir node through all 3 axis positions
local Rotation = {[0]=
11,8,12,10,14,13,16,15,18,15,5,19,21,20,23,22,1,0,3,2,7,4,9,6
}
local function get_conn_dirs(pos, node)
local tbl = {[0]=
{R=2,L=4}, {R=1,L=3}, {R=2,L=4}, {R=1,L=3},
{R=2,L=4}, {D=5,U=6}, {R=2,L=4}, {D=5,U=6},
{R=2,L=4}, {D=5,U=6}, {R=2,L=4}, {D=5,U=6},
{D=5,U=6}, {R=1,L=3}, {D=5,U=6}, {R=1,L=3},
{D=5,U=6}, {R=1,L=3}, {D=5,U=6}, {R=1,L=3},
{R=2,L=4}, {R=1,L=3}, {R=2,L=4}, {R=1,L=3},
}
if M(pos):get_int("turned_off") == 1 then
return {}
end
return tbl[node.param2]
end
local function update_network(pos, node)
-- power.update_network(pos, nil, Cable)
for _,outdir in pairs(get_conn_dirs(pos, node)) do
power.update_network(pos, outdir, Cable)
end
end
local function on_rotate(pos, node, user, mode, new_param2)
if minetest.is_protected(pos, user:get_player_name()) then
return false
end
update_network(pos, node)
node.param2 = Rotation[node.param2]
minetest.swap_node(pos, node)
return true
end
minetest.register_node("techage:powerswitch_box", {
description = S("TA Power Switch Box"),
tiles = {
-- up, down, right, left, back, front
'techage_electric_switch.png',
'techage_electric_switch.png',
'techage_electric_junction.png',
'techage_electric_junction.png',
'techage_electric_switch.png',
'techage_electric_switch.png',
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{ -2/4, -1/4, -1/4, 2/4, 1/4, 1/4},
},
},
after_place_node = function(pos)
Cable:after_place_node(pos)
end,
after_dig_node = function(pos)
Cable:after_dig_node(pos)
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
--print("powerswitch_box tubelib2_on_update2")
update_network(pos, node)
end,
on_rightclick = function(pos, node, clicker)
node.name = "techage:powerswitch_box_off"
minetest.swap_node(pos, node)
M(pos):set_int("turned_off", 1)
minetest.sound_play("techage_button", {
pos = pos,
gain = 0.5,
max_hear_distance = 5,
})
Cable:after_dig_node(pos)
update_network(pos, node)
end,
networks = {
ele1 = {
get_sides = get_conn_dirs,
--sides = networks.AllSides,
ntype = "junc",
},
},
paramtype = "light",
sunlight_propagates = true,
on_rotate = on_rotate,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2, techage_trowel = 1},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("techage:powerswitch_box_off", {
description = S("TA Power Switch Box"),
tiles = {
-- up, down, right, left, back, front
'techage_electric_switch.png',
'techage_electric_switch.png',
'techage_electric_junction.png',
'techage_electric_junction.png',
'techage_electric_switch.png',
'techage_electric_switch.png',
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{ -2/4, -1/4, -1/4, 2/4, 1/4, 1/4},
},
},
after_place_node = function(pos)
Cable:after_place_node(pos)
end,
after_dig_node = function(pos)
Cable:after_dig_node(pos)
end,
tubelib2_on_update2 = function(pos, outdir, tlib2, node)
update_network(pos, node)
end,
on_rightclick = function(pos, node, clicker)
node.name = "techage:powerswitch_box"
minetest.swap_node(pos, node)
M(pos):set_int("turned_off", 0)
minetest.sound_play("techage_button", {
pos = pos,
gain = 0.5,
max_hear_distance = 5,
})
Cable:after_dig_node(pos)
update_network(pos, node)
end,
networks = {
ele1 = {
--sides = {},
--sides = networks.AllSides,
get_sides = get_conn_dirs,
ntype = "", -- unknown type, acting as switch off
},
},
paramtype = "light",
sunlight_propagates = true,
on_rotate = on_rotate,
paramtype2 = "facedir",
drop = "techage:powerswitch_box",
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(),
})
Cable:add_secondary_node_names({"techage:powerswitch_box"})

225
ta3_power/akkubox.lua Normal file
View File

@ -0,0 +1,225 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
TA3 Accu Box
]]--
-- for lazy programmers
local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
local CYCLE_TIME = 2
local PWR_PERF = 10
local PWR_CAPA = 2000
local Cable = techage.ElectricCable
local power = techage.power
local networks = techage.networks
local in_range = techage.in_range
local function formspec(self, pos, nvm)
local needed = nvm.needed or 0
local capa = nvm.capa or 0
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,-0.1;"..minetest.colorize( "#000000", S("TA3 Akku Box")).."]"..
power.formspec_label_bar(0, 0.8, S("Load"), PWR_CAPA, capa)..
"image_button[3,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]"..
"tooltip[3,2;1,1;"..self:get_state_tooltip(nvm).."]"..
"label[4.2,1.2;Flow]"..
"image[4,1.7;1,2;"..techage.power.formspec_load_bar(needed, PWR_PERF).."]"
end
local function start_node(pos, nvm, state)
nvm.running = true
nvm.needed = 0
local outdir = M(pos):get_int("outdir")
power.generator_start(pos, Cable, CYCLE_TIME, outdir)
power.consumer_start(pos, Cable, CYCLE_TIME, outdir)
end
local function stop_node(pos, nvm, state)
nvm.running = false
nvm.needed = 0
local outdir = M(pos):get_int("outdir")
power.generator_stop(pos, Cable, outdir)
power.consumer_stop(pos, Cable, outdir)
end
local State = techage.NodeStates:new({
node_name_passive = "techage:ta3_akku",
cycle_time = CYCLE_TIME,
standby_ticks = 0,
formspec_func = formspec,
start_node = start_node,
stop_node = stop_node,
})
local function node_timer(pos, elapsed)
local nvm = techage.get_nvm(pos)
nvm.capa = nvm.capa or 0
local outdir = M(pos):get_int("outdir")
local taken = 0
local given = 0
if nvm.capa < PWR_CAPA then
taken = power.consumer_alive(pos, Cable, CYCLE_TIME)
end
if nvm.capa > 0 then
given = power.generator_alive(pos, Cable, CYCLE_TIME, outdir)
end
nvm.needed = taken - given
nvm.capa = in_range(nvm.capa + nvm.needed, 0, PWR_CAPA)
--print("node_timer accu "..P2S(pos), nvm.needed, nvm.capa)
if techage.is_activeformspec(pos) then
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
return true
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))
end
local function on_receive_fields(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
end
local nvm = techage.get_nvm(pos)
State:state_button_event(pos, nvm, fields)
M(pos):set_string("formspec", formspec(State, pos, nvm))
end
local function get_capa(itemstack)
local meta = itemstack:get_meta()
if meta then
return in_range(meta:get_int("capa") * (PWR_CAPA/100), 0, 3000)
end
return 0
end
local function set_capa(pos, oldnode, digger, capa)
local node = ItemStack(oldnode.name)
local meta = node:get_meta()
capa = techage.power.percent(PWR_CAPA, capa)
capa = (math.floor((capa or 0) / 5)) * 5
meta:set_int("capa", capa)
local text = S("TA3 Accu Box").." ("..capa.." %)"
meta:set_string("description", text)
local inv = minetest.get_inventory({type="player", name=digger:get_player_name()})
local left_over = inv:add_item("main", node)
if left_over:get_count() > 0 then
minetest.add_item(pos, node)
end
end
local function after_place_node(pos, placer, itemstack)
local meta = M(pos)
local nvm = techage.get_nvm(pos)
local own_num = techage.add_node(pos, "techage:ta3_akku")
meta:set_string("owner", placer:get_player_name())
meta:set_string("infotext", S("TA3 Accu Box").." "..own_num)
meta:set_int("outdir", networks.side_to_outdir(pos, "R"))
meta:set_string("formspec", formspec(State, pos, nvm))
Cable:after_place_node(pos)
State:node_init(pos, nvm, own_num)
nvm.capa = get_capa(itemstack)
end
local function after_dig_node(pos, oldnode, oldmetadata, digger)
local nvm = techage.get_nvm(pos)
Cable:after_dig_node(pos)
set_capa(pos, oldnode, digger, nvm.capa)
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", "con2"},
nominal = PWR_PERF,
},
}
minetest.register_node("techage:ta3_akku", {
description = S("TA3 Accu Box"),
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_frame_ta3.png^techage_appl_hole_electric.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",
},
on_timer = node_timer,
on_rightclick = on_rightclick,
on_receive_fields = on_receive_fields,
after_place_node = after_place_node,
after_dig_node = after_dig_node,
tubelib2_on_update2 = tubelib2_on_update2,
networks = net_def,
drop = "", -- don't remove, item will be added via 'set_capa'
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
on_rotate = screwdriver.disallow,
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
Cable:add_secondary_node_names({"techage:ta3_akku"})
-- for logical communication
techage.register_node({"techage:ta3_akku"}, {
on_recv_message = function(pos, src, topic, payload)
local nvm = techage.get_nvm(pos)
if topic == "load" then
return techage.power.percent(PWR_CAPA, nvm.capa)
elseif topic == "size" then
return PWR_CAPA
else
return State:on_receive_message(pos, topic, payload)
end
end,
on_node_load = function(pos)
local meta = M(pos)
meta:set_int("outdir", networks.side_to_outdir(pos, "R"))
if meta:get_string("node_number") == "" then
local own_num = techage.add_node(pos, "techage:ta3_akku")
meta:set_string("node_number", own_num)
meta:set_string("infotext", S("TA3 Accu Box").." "..own_num)
end
end,
})
minetest.register_craft({
output = "techage:ta3_akku",
recipe = {
{"default:tin_ingot", "default:tin_ingot", "default:wood"},
{"default:copper_ingot", "default:copper_ingot", "techage:electric_cableS"},
{"techage:iron_ingot", "techage:iron_ingot", "default:wood"},
},
})

View File

@ -0,0 +1,280 @@
--[[
TechAge
=======
Copyright (C) 2019-2020 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
TA3 Tiny Power Generator
]]--
-- for lazy programmers
local M = minetest.get_meta
local S = techage.S
local Power = techage.ElectricCable
local firebox = techage.firebox
local power = techage.power
local fuel = techage.fuel
local Pipe = techage.LiquidPipe
local liquid = techage.liquid
local CYCLE_TIME = 2
local PWR_CAPA = 12
local EFFICIENCY = 2.5
local function formspec(self, pos, mem)
local fuel_percent = 0
if mem.running then
fuel_percent = ((mem.burn_cycles or 1) * 100) / (mem.burn_cycles_total or 1)
end
return "size[8,6]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
fuel.formspec_fuel(1, 0, mem)..
"button[1.6,1;1.8,1;update;"..S("Update").."]"..
"image_button[5.5,0.5;1,1;".. self:get_state_button_image(mem) ..";state_button;]"..
"image[6.5,0;1,2;"..power.formspec_power_bar(PWR_CAPA, mem.provided).."]"..
"list[current_player;main;0,2.3;8,4;]"..
default.get_hotbar_bg(0, 3)
end
local function can_start(pos, mem, state)
if mem.burn_cycles > 0 or (mem.liquid and mem.liquid.amount and mem.liquid.amount > 0) then
return true
end
return false
end
local function start_node(pos, mem, state)
mem.running = true
power.generator_start(pos, mem, PWR_CAPA)
minetest.sound_play("techage_generator", {
pos = pos,
gain = 1,
max_hear_distance = 10})
end
local function stop_node(pos, mem, state)
mem.running = false
mem.provided = 0
power.generator_stop(pos, mem)
end
local State = techage.NodeStates:new({
node_name_passive = "techage:tiny_generator",
node_name_active = "techage:tiny_generator_on",
cycle_time = CYCLE_TIME,
standby_ticks = 0,
formspec_func = formspec,
infotext_name = "TA3 Tiny Power Generator",
can_start = can_start,
start_node = start_node,
stop_node = stop_node,
})
local function burning(pos, mem)
local ratio = math.max((mem.provided or PWR_CAPA) / PWR_CAPA, 0.02)
mem.liquid = mem.liquid or {}
mem.liquid.amount = mem.liquid.amount or 0
mem.burn_cycles = (mem.burn_cycles or 0) - ratio
if mem.burn_cycles <= 0 then
if mem.liquid.amount > 0 then
mem.liquid.amount = mem.liquid.amount - 1
mem.burn_cycles = fuel.burntime(mem.liquid.name) * EFFICIENCY / CYCLE_TIME
mem.burn_cycles_total = mem.burn_cycles
return true
else
mem.liquid.name = nil
State:fault(pos, mem)
return false
end
else
return true
end
end
local function node_timer(pos, elapsed)
local mem = tubelib2.get_mem(pos)
if mem.running and burning(pos, mem) then
mem.provided = power.generator_alive(pos, mem)
minetest.sound_play("techage_generator", {
pos = pos,
gain = 1,
max_hear_distance = 10})
return true
else
mem.provided = 0
end
return false
end
local function on_receive_fields(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
end
local mem = tubelib2.get_mem(pos)
State:state_button_event(pos, mem, fields)
M(pos):set_string("formspec", formspec(State, pos, mem))
end
local function formspec_clbk(pos, mem)
return formspec(State, pos, mem)
end
local function on_metadata_inventory_put(pos, listname, index, stack, player)
minetest.after(0.5, fuel.move_item, pos, stack, formspec_clbk)
end
local function on_rightclick(pos)
local mem = tubelib2.get_mem(pos)
M(pos):set_string("formspec", formspec(State, pos, mem))
end
local _liquid = {
fuel_cat = fuel.BT_NAPHTHA,
capa = fuel.CAPACITY,
peek = liquid.srv_peek,
put = function(pos, indir, name, amount)
if fuel.valid_fuel(name, fuel.BT_NAPHTHA) then
return liquid.srv_put(pos, indir, name, amount)
end
return amount
end,
take = liquid.srv_take,
}
local _networks = {
pipe = {
sides = techage.networks.AllSides, -- Pipe connection sides
ntype = "tank",
},
}
minetest.register_node("techage:tiny_generator", {
description = S("TA3 Tiny Power Generator"),
tiles = {
-- up, down, right, left, back, front
"techage_appl_electric_gen_top.png^techage_frame_ta3_top.png",
"techage_appl_electric_gen_top.png^techage_frame_ta3.png",
"techage_appl_electric_gen_side.png^techage_appl_hole_electric.png^techage_frame_ta3.png",
"techage_appl_electric_gen_side.png^techage_frame_ta3.png",
"techage_appl_electric_gen_front.png^[transformFX]^techage_frame_ta3.png",
"techage_appl_electric_gen_front.png^techage_frame_ta3.png",
},
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
on_rotate = screwdriver.disallow,
is_ground_content = false,
on_construct = function(pos)
local mem = tubelib2.init_mem(pos)
local number = techage.add_node(pos, "techage:tiny_generator")
mem.running = false
mem.burn_cycles = 0
State:node_init(pos, mem, number)
local meta = M(pos)
meta:set_string("formspec", formspec(State, pos, mem))
local inv = meta:get_inventory()
inv:set_size('fuel', 1)
end,
allow_metadata_inventory_put = fuel.allow_metadata_inventory_put,
allow_metadata_inventory_take = fuel.allow_metadata_inventory_take,
on_metadata_inventory_put = on_metadata_inventory_put,
on_receive_fields = on_receive_fields,
on_rightclick = on_rightclick,
on_timer = node_timer,
can_dig = fuel.can_dig,
liquid = _liquid,
networks = _networks,
})
minetest.register_node("techage:tiny_generator_on", {
description = S("TA3 Tiny Power Generator"),
tiles = {
-- up, down, right, left, back, front
"techage_appl_electric_gen_top.png^techage_frame_ta3_top.png",
"techage_appl_electric_gen_top.png^techage_frame_ta3.png",
"techage_appl_electric_gen_side.png^techage_appl_hole_electric.png^techage_frame_ta3.png",
"techage_appl_electric_gen_side.png^techage_frame_ta3.png",
{
image = "techage_appl_electric_gen_front4.png^[transformFX]^techage_frame4_ta3.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 0.8,
},
},
{
image = "techage_appl_electric_gen_front4.png^techage_frame4_ta3.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 0.8,
},
},
},
paramtype = "light",
paramtype2 = "facedir",
groups = {not_in_creative_inventory=1},
diggable = false,
light_source = 4,
on_rotate = screwdriver.disallow,
is_ground_content = false,
allow_metadata_inventory_put = fuel.allow_metadata_inventory_put,
allow_metadata_inventory_take = fuel.allow_metadata_inventory_take,
on_metadata_inventory_put = on_metadata_inventory_put,
on_receive_fields = on_receive_fields,
on_rightclick = on_rightclick,
on_timer = node_timer,
can_dig = fuel.can_dig,
liquid = _liquid,
networks = _networks,
})
Pipe:add_secondary_node_names({"techage:tiny_generator", "techage:tiny_generator_on"})
techage.power.register_node({"techage:tiny_generator", "techage:tiny_generator_on"}, {
conn_sides = {"R"},
power_network = Power,
})
techage.register_node({"techage:tiny_generator", "techage:tiny_generator_on"}, {
on_recv_message = function(pos, src, topic, payload)
local mem = tubelib2.get_mem(pos)
if topic == "load" then
return power.percent(PWR_CAPA, mem.provided)
else
return State:on_receive_message(pos, topic, payload)
end
end,
on_node_load = function(pos)
State:on_node_load(pos)
end,
})
minetest.register_craft({
output = "techage:tiny_generator",
recipe = {
{'default:steel_ingot', 'techage:usmium_nuggets', 'default:steel_ingot'},
{'dye:red', 'basic_materials:gear_steel', 'techage:electric_cableS'},
{'default:steel_ingot', 'techage:vacuum_tube', 'default:steel_ingot'},
},
})