From 762347521c0baa5e664e6e43215956a94e6906b6 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Sun, 9 Feb 2020 21:09:09 +0100 Subject: [PATCH] chemical reactor added, further bugfixes --- basis/boiler_lib.lua | 1 + basis/fuel_lib.lua | 118 ++---------- chemistry/ta4_doser.lua | 12 +- chemistry/ta4_stand.lua | 91 ++++++---- coal_power_station/firebox.lua | 46 +++-- coal_power_station/oilfirebox.lua | 289 +++++------------------------- furnace/firebox.lua | 1 - init.lua | 5 +- liquids/fuel_lib.lua | 268 --------------------------- oil/distiller.lua | 2 +- oil/reboiler.lua | 40 ++++- power/distribution.lua | 2 +- sounds/techage_reactor.ogg | Bin 15384 -> 8799 bytes 13 files changed, 194 insertions(+), 681 deletions(-) delete mode 100644 liquids/fuel_lib.lua diff --git a/basis/boiler_lib.lua b/basis/boiler_lib.lua index f93b747..929bb80 100644 --- a/basis/boiler_lib.lua +++ b/basis/boiler_lib.lua @@ -67,6 +67,7 @@ end function techage.boiler.water_temperature(pos, nvm) nvm.temperature = nvm.temperature or 20 nvm.num_water = nvm.num_water or 0 + nvm.water_level = nvm.water_level or 0 if nvm.fire_trigger then nvm.temperature = math.min(nvm.temperature + HEAT_STEP, 100) else diff --git a/basis/fuel_lib.lua b/basis/fuel_lib.lua index 7b48fa4..df46357 100644 --- a/basis/fuel_lib.lua +++ b/basis/fuel_lib.lua @@ -71,91 +71,6 @@ function techage.fuel.formspec(nvm) techage.fuel.fuel_container(1.5, 1, nvm) end ---local function fill_container(pos, inv, nvm) --- nvm.liquid = nvm.liquid or {} --- nvm.liquid.amount = nvm.liquid.amount or 0 --- local empty_container = inv:get_stack("fuel", 1):get_name() --- local full_container = liquid.get_full_container(empty_container, nvm.liquid.name) --- if empty_container and full_container then --- local ldef = liquid.get_liquid_def(full_container) --- if ldef and nvm.liquid.amount - ldef.size >= 0 then --- inv:remove_item("fuel", ItemStack(empty_container)) --- inv:add_item("fuel", ItemStack(full_container)) --- nvm.liquid.amount = nvm.liquid.amount - ldef.size --- if nvm.liquid.amount == 0 then --- nvm.liquid.name = nil --- end --- end --- end ---end - ---local function empty_container(pos, inv, nvm) --- nvm.liquid = nvm.liquid or {} --- nvm.liquid.amount = nvm.liquid.amount or 0 --- local stack = inv:get_stack("fuel", 1) --- if stack:get_count() == 1 then --- local ldef = liquid.get_liquid_def(stack:get_name()) --- if ldef and ValidOilFuels[ldef.inv_item] then --- if not nvm.liquid.name or ldef.inv_item == nvm.liquid.name then --- if nvm.liquid.amount + ldef.size <= CAPACITY then --- inv:remove_item("fuel", stack) --- inv:add_item("fuel", ItemStack(ldef.container)) --- nvm.liquid.amount = nvm.liquid.amount + ldef.size --- nvm.liquid.name = ldef.inv_item --- end --- end --- end --- end ---end - ---local function move_item(pos, stack) --- local nvm = techage.get_nvm(pos) --- local inv = M(pos):get_inventory() --- if liquid.is_container_empty(stack:get_name()) then --- fill_container(pos, inv, nvm) --- else --- empty_container(pos, inv, nvm) --- end --- M(pos):set_string("formspec", techage.fuel.formspec(nvm)) ---end - ---function techage.fuel.move_item(pos, stack, formspec) --- local nvm = techage.get_nvm(pos) --- local inv = M(pos):get_inventory() --- if liquid.is_container_empty(stack:get_name()) then --- fill_container(pos, inv, nvm) --- else --- empty_container(pos, inv, nvm) --- end --- M(pos):set_string("formspec", formspec(pos, nvm)) ---end - ---function techage.fuel.allow_metadata_inventory_put(pos, listname, index, stack, player) --- if minetest.is_protected(pos, player:get_player_name()) then --- return 0 --- end --- if liquid.is_container_empty(stack:get_name()) then --- return 1 --- end --- local category = LQD(pos).fuel_cat --- local ldef = liquid.get_liquid_def(stack:get_name()) --- if ldef and ValidOilFuels[ldef.inv_item] and ValidOilFuels[ldef.inv_item] <= category then --- return 1 --- end --- return 0 ---end - ---function techage.fuel.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 - ---function techage.fuel.on_metadata_inventory_put(pos, listname, index, stack, player) --- minetest.after(0.5, move_item, pos, stack) ---end - function techage.fuel.can_dig(pos, player) if minetest.is_protected(pos, player:get_player_name()) then return false @@ -173,22 +88,6 @@ function techage.fuel.on_rightclick(pos, node, clicker) M(pos):set_string("formspec", techage.fuel.formspec(nvm)) end ---function techage.fuel.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) --- nvm.countdown = 10 --- M(pos):set_string("formspec", techage.fuel.formspec(nvm)) ---end - ---function techage.fuel.formspec_update(pos, nvm) --- if nvm.countdown and nvm.countdown > 0 then --- nvm.countdown = nvm.countdown - 1 --- M(pos):set_string("formspec", techage.fuel.formspec(nvm)) --- end ---end - -- name is the fuel item name function techage.fuel.burntime(name) if ValidOilFuels[name] then @@ -229,3 +128,20 @@ function techage.fuel.on_punch(pos, node, puncher, pointed_thing) end end end + +function techage.fuel.get_fuel(nvm) + if nvm.liquid and nvm.liquid.name and nvm.liquid.amount then + if nvm.liquid.amount > 0 then + nvm.liquid.amount = nvm.liquid.amount - 1 + return nvm.liquid.name + end + nvm.liquid.name = nil + end + return nil +end + +function techage.fuel.has_fuel(nvm) + nvm.liquid = nvm.liquid or {} + nvm.liquid.amount = nvm.liquid.amount or 0 + return nvm.liquid.amount > 0 +end \ No newline at end of file diff --git a/chemistry/ta4_doser.lua b/chemistry/ta4_doser.lua index cd3dd43..dca4a4e 100644 --- a/chemistry/ta4_doser.lua +++ b/chemistry/ta4_doser.lua @@ -48,15 +48,15 @@ local function get_starter_name(pos) end local function formspec(self, pos, nvm) - return "size[8,7]".. + return "size[6,3.6]".. default.gui_bg.. default.gui_bg_img.. default.gui_slots.. - recipes.formspec(0, 0, "ta4_doser", nvm).. - "image_button[6,1;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. - "tooltip[6,1;1,1;"..self:get_state_tooltip(nvm).."]".. - "list[current_player;main;0,3.3;8,4;]" .. - default.get_hotbar_bg(0, 3.5) + "box[0,-0.1;5.8,0.5;#c6e8ff]".. + "label[2.5,-0.1;"..minetest.colorize( "#000000", S("Doser")).."]".. + recipes.formspec(0.1, 0.8, "ta4_doser", nvm).. + "image_button[5,2;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. + "tooltip[5,2;1,1;"..self:get_state_tooltip(nvm).."]" end local function get_liquids(pos) diff --git a/chemistry/ta4_stand.lua b/chemistry/ta4_stand.lua index 8ef275c..dd70661 100644 --- a/chemistry/ta4_stand.lua +++ b/chemistry/ta4_stand.lua @@ -3,7 +3,7 @@ TechAge ======= - Copyright (C) 2019 Joachim Stolberg + Copyright (C) 2019-2020 Joachim Stolberg GPL v3 See LICENSE.txt for more information @@ -23,16 +23,39 @@ local liquid = techage.liquid local PWR_NEEDED = 8 local CYCLE_TIME = 4 -local function on_power(pos, nvm) - if nvm.running then - minetest.get_node_timer(pos):start(CYCLE_TIME) - M(pos):set_string("infotext", S("on")) - nvm.has_power = true +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_reactor", { + pos = pos, + gain = 0.5, + max_hear_distance = 10, + loop = true}) + if mem.handle == -1 then + minetest.after(1, play_sound, pos) + end end end -local function on_nopower(pos, nvm) +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 on_power(pos) + M(pos):set_string("infotext", S("on")) + play_sound(pos) + local nvm = techage.get_nvm(pos) + nvm.has_power = 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 end @@ -71,29 +94,25 @@ minetest.register_node("techage:ta4_reactor_stand", { after_place_node = function(pos, placer) local nvm = techage.get_nvm(pos) - techage.power.after_place_node(pos) M(pos):set_string("infotext", S("off")) M(pos):set_int("outdir", networks.side_to_outdir(pos, "R")) Pipe:after_place_node(pos) + Cable:after_place_node(pos) end, tubelib2_on_update2 = function(pos, dir, tlib2, node) - liquid.update_network(pos) - end, - after_tube_update = function(node, pos, out_dir, peer_pos, peer_in_dir) - techage.power.after_tube_update2(node, pos, out_dir, peer_pos, peer_in_dir) + if tlib2.tube_type == "ele1" then + power.update_network(pos, dir, tlib2) + else + liquid.update_network(pos, dir, tlib2) + end end, on_timer = function(pos, elapsed) - local nvm = techage.get_nvm(pos) - power.consumer_alive(pos, nvm) - minetest.sound_play("techage_reactor", { - pos = pos, - gain = 0.5, - max_hear_distance = 10}) - return nvm.running + power.consumer_alive(pos, Cable, CYCLE_TIME) + return true end, after_dig_node = function(pos, oldnode) - techage.power.after_dig_node(pos, oldnode) Pipe:after_dig_node(pos) + Cable:after_dig_node(pos) techage.del_mem(pos) end, @@ -103,23 +122,22 @@ minetest.register_node("techage:ta4_reactor_stand", { groups = {cracky=2}, is_ground_content = false, sounds = default.node_sound_metal_defaults(), - -- Pipe connection + networks = { pipe2 = { sides = {R=1}, ntype = "pump", }, + ele1 = { + sides = {L=1}, + ntype = "con1", + on_power = on_power, + on_nopower = on_nopower, + nominal = PWR_NEEDED, + }, }, }) --- for electrical connections -techage.power.enrich_node({"techage:ta4_reactor_stand"}, { - conn_sides = {"L"}, - power_network = Cable, - on_power = on_power, - on_nopower = on_nopower, -}) - -- controlled by the fillerpipe techage.register_node({"techage:ta4_reactor_stand"}, { on_transfer = function(pos, in_dir, topic, payload) @@ -131,14 +149,13 @@ techage.register_node({"techage:ta4_reactor_stand"}, { return liquid.put(pos, outdir, payload.name, payload.amount, payload.player_name) elseif topic == "can_start" then return power.power_available(pos, Cable) - elseif topic == "start" and payload then - nvm.running = true + elseif topic == "start" then nvm.has_power = false power.consumer_start(pos, Cable, CYCLE_TIME) + minetest.get_node_timer(pos):start(CYCLE_TIME) M(pos):set_string("infotext", "...") return true elseif topic == "stop" then - nvm.running = false nvm.has_power = false power.consumer_stop(pos, Cable) minetest.get_node_timer(pos):stop() @@ -146,6 +163,12 @@ techage.register_node({"techage:ta4_reactor_stand"}, { return true end end, + on_node_load = function(pos, node) + local nvm = techage.get_nvm(pos) + if nvm.has_power then + play_sound(pos) + end + end, }) minetest.register_node("techage:ta4_reactor_base", { @@ -165,7 +188,7 @@ minetest.register_node("techage:ta4_reactor_base", { Pipe:after_place_node(pos) end, tubelib2_on_update2 = function(pos, dir, tlib2, node) - liquid.update_network(pos) + liquid.update_network(pos, dir, tlib2) end, after_dig_node = function(pos, oldnode, oldmetadata, digger) Pipe:after_dig_node(pos) @@ -190,6 +213,8 @@ Pipe:add_secondary_node_names({ "techage:ta4_reactor_stand", }) +Cable:add_secondary_node_names({"techage:ta4_reactor_stand"}) + minetest.register_craft({ output = 'techage:ta4_reactor_stand', recipe = { diff --git a/coal_power_station/firebox.lua b/coal_power_station/firebox.lua index 9634035..4a10fbe 100644 --- a/coal_power_station/firebox.lua +++ b/coal_power_station/firebox.lua @@ -36,33 +36,31 @@ end local function node_timer(pos, elapsed) local nvm = techage.get_nvm(pos) - if nvm.running then - local power = techage.transfer( - {x=pos.x, y=pos.y+2, z=pos.z}, - nil, -- outdir - "trigger", -- topic - nil, -- payload - nil, -- network - {"techage:coalboiler_top"} -- nodenames - ) - nvm.burn_cycles = (nvm.burn_cycles or 0) - math.max((power or 0.02), 0.02) - if nvm.burn_cycles <= 0 then - local taken = firebox.get_fuel(pos) - if taken then - nvm.burn_cycles = (firebox.Burntime[taken:get_name()] or 1) / CYCLE_TIME * BURN_CYCLE_FACTOR - nvm.burn_cycles_total = nvm.burn_cycles - else - nvm.running = false - firehole(pos, false) - M(pos):set_string("formspec", firebox.formspec(nvm)) - return false - end - end - if techage.is_activeformspec(pos) then + local power = techage.transfer( + {x=pos.x, y=pos.y+2, z=pos.z}, + nil, -- outdir + "trigger", -- topic + nil, -- payload + nil, -- network + {"techage:coalboiler_top"} -- nodenames + ) + nvm.burn_cycles = (nvm.burn_cycles or 0) - math.max((power or 0.02), 0.02) + if nvm.burn_cycles <= 0 then + local taken = firebox.get_fuel(pos) + if taken then + nvm.burn_cycles = (firebox.Burntime[taken:get_name()] or 1) / CYCLE_TIME * BURN_CYCLE_FACTOR + nvm.burn_cycles_total = nvm.burn_cycles + else + nvm.running = false + firehole(pos, false) M(pos):set_string("formspec", firebox.formspec(nvm)) + return false end - return true end + if techage.is_activeformspec(pos) then + M(pos):set_string("formspec", firebox.formspec(nvm)) + end + return true end local function start_firebox(pos, nvm) diff --git a/coal_power_station/oilfirebox.lua b/coal_power_station/oilfirebox.lua index 16dba80..9c9cfbb 100644 --- a/coal_power_station/oilfirebox.lua +++ b/coal_power_station/oilfirebox.lua @@ -3,7 +3,7 @@ TechAge ======= - Copyright (C) 2019 Joachim Stolberg + Copyright (C) 2019-2020 Joachim Stolberg GPL v3 See LICENSE.txt for more information @@ -23,7 +23,7 @@ local Pipe = techage.LiquidPipe local liquid = techage.liquid local CYCLE_TIME = 2 -local EFFICIENCY = 0.5 +local BURN_CYCLE_FACTOR = 0.5 local function firehole(pos, on) local param2 = techage.get_node_lvm(pos).param2 @@ -39,36 +39,35 @@ end local function node_timer(pos, elapsed) local nvm = techage.get_nvm(pos) - if nvm.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 - (nvm.power_level or 4)/4.0, -- payload - nil, -- network - {"techage:coalboiler_top"} -- nodenames - ) - ratio = math.max((ratio or 0.02), 0.02) - nvm.burn_cycles = (nvm.burn_cycles or 0) - ratio - if nvm.burn_cycles <= 0 then - local taken = firebox.get_fuel(pos) - if taken then - nvm.burn_cycles = (firebox.Burntime[taken:get_name()] or 1) * EFFICIENCY / CYCLE_TIME - nvm.burn_cycles_total = nvm.burn_cycles - else - nvm.running = false - firehole(pos, false) - M(pos):set_string("formspec", firebox.formspec(nvm)) - return false - end + local power = techage.transfer( + {x=pos.x, y=pos.y+2, z=pos.z}, + nil, -- outdir + "trigger", -- topic + nil, -- payload + nil, -- network + {"techage:coalboiler_top"} -- nodenames + ) + nvm.burn_cycles = (nvm.burn_cycles or 0) - math.max((power or 0.02), 0.02) + if nvm.burn_cycles <= 0 then + local liq_name = fuel.get_fuel(nvm) + if liq_name then + nvm.burn_cycles = fuel.burntime(liq_name) / CYCLE_TIME * BURN_CYCLE_FACTOR + nvm.burn_cycles_total = nvm.burn_cycles + else + nvm.running = false + firehole(pos, false) + M(pos):set_string("formspec", fuel.formspec(nvm)) + return false end - return true end + if techage.is_activeformspec(pos) then + M(pos):set_string("formspec", fuel.formspec(nvm)) + end + return true end local function start_firebox(pos, nvm) - if not nvm.running then + if not nvm.running and fuel.has_fuel(nvm) then nvm.running = true node_timer(pos, 0) firehole(pos, true) @@ -76,162 +75,6 @@ local function start_firebox(pos, nvm) 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 nvm = techage.get_nvm(pos) - techage.add_node(pos, "techage:coalfirebox") - nvm.running = false - nvm.burn_cycles = 0 - nvm.power_level = 4 - local meta = M(pos) - meta:set_string("formspec", firebox.formspec(nvm)) - 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 nvm = techage.get_nvm(pos) - start_firebox(pos, nvm) - M(pos):set_string("formspec", firebox.formspec(nvm)) - 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 nvm = techage.get_nvm(pos) - if nvm.running then - fuel.formspec_update(pos, nvm) - -- 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 - (nvm.power_level or 4)/4.0, -- payload - nil, -- network - {"techage:coalboiler_top"} -- nodenames - ) - ratio = math.max((ratio or 0.02), 0.02) - nvm.burn_cycles = (nvm.burn_cycles or 0) - ratio - nvm.liquid = nvm.liquid or {} - nvm.liquid.amount = nvm.liquid.amount or 0 - if nvm.burn_cycles <= 0 then - if nvm.liquid.amount > 0 then - nvm.liquid.amount = nvm.liquid.amount - 1 - nvm.burn_cycles = fuel.burntime(nvm.liquid.name) * EFFICIENCY / CYCLE_TIME - nvm.burn_cycles_total = nvm.burn_cycles - else - nvm.running = false - nvm.liquid.name = nil - firehole(pos, false) - M(pos):set_string("formspec", fuel.formspec(nvm)) - return false - end - end - return true - end -end - -local function start_firebox2(pos, nvm) - if not nvm.running and nvm.liquid.amount > 0 then - nvm.running = true - on_timer2(pos, 0) - firehole(pos, true) - minetest.get_node_timer(pos):start(CYCLE_TIME) - M(pos):set_string("formspec", fuel.formspec(nvm)) - end -end - minetest.register_node("techage:oilfirebox", { description = S("TA3 Power Station Oil Burner"), inventory_image = "techage_oil_boiler_inv.png", @@ -250,16 +93,17 @@ minetest.register_node("techage:oilfirebox", { is_ground_content = false, sounds = default.node_sound_stone_defaults(), - on_timer = on_timer2, + on_timer = node_timer, 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, + allow_metadata_inventory_take = fuel.allow_metadata_inventory_take, on_rightclick = fuel.on_rightclick, + on_receive_fields = fuel.on_receive_fields, + on_punch = fuel.on_punch, on_construct = function(pos) - local nvm = techage.get_nvm(pos) techage.add_node(pos, "techage:oilfirebox") + local nvm = techage.get_nvm(pos) nvm.running = false nvm.burn_cycles = 0 nvm.liquid = {} @@ -279,7 +123,7 @@ minetest.register_node("techage:oilfirebox", { local nvm = techage.get_nvm(pos) nvm.liquid = nvm.liquid or {} nvm.liquid.amount = nvm.liquid.amount or 0 - minetest.after(1, start_firebox2, pos, nvm) + minetest.after(1, start_firebox, pos, nvm) fuel.on_metadata_inventory_put(pos, listname, index, stack, player) end, @@ -293,15 +137,26 @@ minetest.register_node("techage:oilfirebox", { local nvm = techage.get_nvm(pos) nvm.liquid = nvm.liquid or {} nvm.liquid.amount = nvm.liquid.amount or 0 - start_firebox2(pos, nvm) + 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 = liquid.srv_take, + 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 = { - pipe = { + pipe2 = { sides = techage.networks.AllSides, -- Pipe connection sides ntype = "tank", }, @@ -311,45 +166,6 @@ minetest.register_node("techage:oilfirebox", { 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 nvm = techage.get_nvm(pos) - start_firebox(pos, nvm) - 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 nvm = techage.get_nvm(pos) - if topic == "state" then - if nvm.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 nvm = techage.get_nvm(pos) @@ -367,15 +183,6 @@ techage.register_node({"techage:oilfirebox"}, { 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 = { @@ -388,9 +195,11 @@ minetest.register_craft({ minetest.register_lbm({ label = "[techage] Power Station firebox", name = "techage:steam_engine", - nodenames = {"techage:coalfirebox", "techage:oilfirebox"}, + nodenames = {"techage:oilfirebox"}, run_at_every_load = true, action = function(pos, node) + local nvm = techage.get_nvm(pos) + nvm.running = true minetest.get_node_timer(pos):start(CYCLE_TIME) end }) diff --git a/furnace/firebox.lua b/furnace/firebox.lua index 395f67d..760fbd6 100644 --- a/furnace/firebox.lua +++ b/furnace/firebox.lua @@ -41,7 +41,6 @@ local function node_timer(pos, elapsed) nvm.liquid = nvm.liquid or {} nvm.liquid.amount = nvm.liquid.amount or 0 if nvm.running then - fuel.formspec_update(pos, nvm) nvm.burn_cycles = (nvm.burn_cycles or 0) - 1 if nvm.burn_cycles <= 0 then if nvm.liquid.amount > 0 then diff --git a/init.lua b/init.lua index abe4bd8..c153e85 100644 --- a/init.lua +++ b/init.lua @@ -119,6 +119,7 @@ else dofile(MP.."/coal_power_station/generator.lua") dofile(MP.."/coal_power_station/turbine.lua") dofile(MP.."/coal_power_station/cooler.lua") + dofile(MP.."/coal_power_station/oilfirebox.lua") -- -- Industrial Furnace dofile(MP.."/furnace/firebox.lua") @@ -199,8 +200,8 @@ else -- -- Chemistry dofile(MP.."/chemistry/ta4_reactor.lua") --- dofile(MP.."/chemistry/ta4_stand.lua") --- dofile(MP.."/chemistry/ta4_doser.lua") + dofile(MP.."/chemistry/ta4_stand.lua") + dofile(MP.."/chemistry/ta4_doser.lua") -- -- Hydrogen -- dofile(MP.."/hydrogen/fuelcellstack.lua") diff --git a/liquids/fuel_lib.lua b/liquids/fuel_lib.lua deleted file mode 100644 index 9646895..0000000 --- a/liquids/fuel_lib.lua +++ /dev/null @@ -1,268 +0,0 @@ ---[[ - - TechAge - ======= - - Copyright (C) 2019-2020 Joachim Stolberg - - GPL v3 - See LICENSE.txt for more information - - Oil fuel burning lib - -]]-- - -local S2P = minetest.string_to_pos -local P2S = minetest.pos_to_string -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 ValidOilFuels = techage.firebox.ValidOilFuels -local Burntime = techage.firebox.Burntime - -techage.fuel = {} - -local CAPACITY = 50 -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 - - -function techage.fuel.fuel_container(x, y, nvm) - local itemname = "" - if nvm.liquid and nvm.liquid.name and nvm.liquid.amount and nvm.liquid.amount > 0 then - itemname = nvm.liquid.name.." "..nvm.liquid.amount - end - local fuel_percent = 0 - if nvm.running then - fuel_percent = ((nvm.burn_cycles or 1) * 100) / (nvm.burn_cycles_total or 1) - end - return "container["..x..","..y.."]".. - "box[0,0;1.05,2.1;#000000]".. - "image[0.1,0.1;1,1;default_furnace_fire_bg.png^[lowpart:".. - fuel_percent..":default_furnace_fire_fg.png]".. - techage.item_image(0.1, 1.1, itemname).. - "container_end[]" -end - -local function help(x, y) - local tooltip = S("To add fuel punch\nthis block\nwith a fuel container") - return "label["..x..","..y..";"..minetest.colorize("#000000", minetest.formspec_escape("[?]")).."]".. - "tooltip["..x..","..y..";0.5,0.5;"..tooltip..";#0C3D32;#FFFFFF]" -end - -function techage.fuel.formspec(nvm) - local title = S("Fuel Menu") - return "size[4,3]".. - default.gui_bg.. - default.gui_bg_img.. - default.gui_slots.. - "box[0,-0.1;3.8,0.5;#c6e8ff]".. - "label[1,-0.1;"..minetest.colorize("#000000", title).."]".. - help(3.4, -0.1).. - techage.fuel.fuel_container(1.5, 1, nvm) -end - ---local function fill_container(pos, inv, nvm) --- nvm.liquid = nvm.liquid or {} --- nvm.liquid.amount = nvm.liquid.amount or 0 --- local empty_container = inv:get_stack("fuel", 1):get_name() --- local full_container = liquid.get_full_container(empty_container, nvm.liquid.name) --- if empty_container and full_container then --- local ldef = liquid.get_liquid_def(full_container) --- if ldef and nvm.liquid.amount - ldef.size >= 0 then --- inv:remove_item("fuel", ItemStack(empty_container)) --- inv:add_item("fuel", ItemStack(full_container)) --- nvm.liquid.amount = nvm.liquid.amount - ldef.size --- if nvm.liquid.amount == 0 then --- nvm.liquid.name = nil --- end --- end --- end ---end - ---local function empty_container(pos, inv, nvm) --- nvm.liquid = nvm.liquid or {} --- nvm.liquid.amount = nvm.liquid.amount or 0 --- local stack = inv:get_stack("fuel", 1) --- if stack:get_count() == 1 then --- local ldef = liquid.get_liquid_def(stack:get_name()) --- if ldef and ValidOilFuels[ldef.inv_item] then --- if not nvm.liquid.name or ldef.inv_item == nvm.liquid.name then --- if nvm.liquid.amount + ldef.size <= CAPACITY then --- inv:remove_item("fuel", stack) --- inv:add_item("fuel", ItemStack(ldef.container)) --- nvm.liquid.amount = nvm.liquid.amount + ldef.size --- nvm.liquid.name = ldef.inv_item --- end --- end --- end --- end ---end - ---local function move_item(pos, stack) --- local nvm = techage.get_nvm(pos) --- local inv = M(pos):get_inventory() --- if liquid.is_container_empty(stack:get_name()) then --- fill_container(pos, inv, nvm) --- else --- empty_container(pos, inv, nvm) --- end --- M(pos):set_string("formspec", techage.fuel.formspec(nvm)) ---end - ---function techage.fuel.move_item(pos, stack, formspec) --- local nvm = techage.get_nvm(pos) --- local inv = M(pos):get_inventory() --- if liquid.is_container_empty(stack:get_name()) then --- fill_container(pos, inv, nvm) --- else --- empty_container(pos, inv, nvm) --- end --- M(pos):set_string("formspec", formspec(pos, nvm)) ---end - ---function techage.fuel.allow_metadata_inventory_put(pos, listname, index, stack, player) --- if minetest.is_protected(pos, player:get_player_name()) then --- return 0 --- end --- if liquid.is_container_empty(stack:get_name()) then --- return 1 --- end --- local category = LQD(pos).fuel_cat --- local ldef = liquid.get_liquid_def(stack:get_name()) --- if ldef and ValidOilFuels[ldef.inv_item] and ValidOilFuels[ldef.inv_item] <= category then --- return 1 --- end --- return 0 ---end - ---function techage.fuel.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 - ---function techage.fuel.on_metadata_inventory_put(pos, listname, index, stack, player) --- minetest.after(0.5, move_item, pos, stack) ---end - -function techage.fuel.can_dig(pos, player) - if minetest.is_protected(pos, player:get_player_name()) then - return false - end - local nvm = techage.get_nvm(pos) - nvm.liquid = nvm.liquid or {} - nvm.liquid.amount = nvm.liquid.amount or 0 - local inv = M(pos):get_inventory() - return inv:is_empty("fuel") and nvm.liquid.amount == 0 -end - -function techage.fuel.on_rightclick(pos, node, clicker) - techage.set_activeformspec(pos, clicker) - local nvm = techage.get_nvm(pos) - M(pos):set_string("formspec", techage.fuel.formspec(nvm)) -end - ---function techage.fuel.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) --- nvm.countdown = 10 --- M(pos):set_string("formspec", techage.fuel.formspec(nvm)) ---end - ---function techage.fuel.formspec_update(pos, nvm) --- if nvm.countdown and nvm.countdown > 0 then --- nvm.countdown = nvm.countdown - 1 --- M(pos):set_string("formspec", techage.fuel.formspec(nvm)) --- end ---end - --- name is the fuel item name -function techage.fuel.burntime(name) - if ValidOilFuels[name] then - return Burntime[name] or 0.01 -- not zero ! - end - return 0.01 -- not zero ! -end - -function techage.fuel.valid_fuel(name, category) - return ValidOilFuels[name] and ValidOilFuels[name] <= category -end - --- check if the given empty container can be replaced by a full --- container and added to the players inventory -local function fill(nvm, empty_container, item_count, puncher) - nvm.liquid = nvm.liquid or {} - nvm.liquid.amount = nvm.liquid.amount or 0 - local full_container = liquid.get_full_container(empty_container, nvm.liquid.name) - if empty_container and full_container then - local item = ItemStack(full_container) -- to be added - local ldef = liquid.get_liquid_def(full_container) - if ldef and nvm.liquid.amount - ldef.size >= 0 then - if item_count > 1 then -- can't be simply replaced? - -- check for extra free space - local inv = puncher:get_inventory() - if inv:room_for_item("main", item) then - -- add full container and return - -- the empty once - 1 - inv:add_item("main", item) - item = {name = empty_container, count = item_count - 1} - else - return -- no free space - end - end - nvm.liquid.amount = nvm.liquid.amount - ldef.size - if nvm.liquid.amount == 0 then - nvm.liquid.name = nil - end - return item -- to be added to the players inv. - end - end -end - -local function empty(nvm, full_container) - nvm.liquid = nvm.liquid or {} - nvm.liquid.amount = nvm.liquid.amount or 0 - local ldef = liquid.get_liquid_def(full_container) - if ldef and ValidOilFuels[ldef.inv_item] then - if not nvm.liquid.name or ldef.inv_item == nvm.liquid.name then - if nvm.liquid.amount + ldef.size <= CAPACITY then - nvm.liquid.amount = nvm.liquid.amount + ldef.size - nvm.liquid.name = ldef.inv_item - return ItemStack(ldef.container) - end - end - end -end - -function techage.fuel.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 - - local wielded_item = puncher:get_wielded_item():get_name() - local item_count = puncher:get_wielded_item():get_count() - local new_item = fill(nvm, wielded_item, item_count, puncher) - or empty(nvm, wielded_item) - if new_item then - puncher:set_wielded_item(ItemStack(new_item)) - M(pos):set_string("formspec", techage.fuel.formspec(pos, nvm)) - mem.blocking_time = techage.SystemTime + BLOCKING_TIME - return - end -end diff --git a/oil/distiller.lua b/oil/distiller.lua index 64d803f..2a33f50 100644 --- a/oil/distiller.lua +++ b/oil/distiller.lua @@ -41,7 +41,7 @@ local function after_place_node(pos, placer) end local function tubelib2_on_update2(pos, dir, tlib2, node) - liquid.update_network(pos) + liquid.update_network(pos, dir, tlib2) end local function after_dig_node(pos, oldnode, oldmetadata, digger) diff --git a/oil/reboiler.lua b/oil/reboiler.lua index 686dc4e..ed7f11d 100644 --- a/oil/reboiler.lua +++ b/oil/reboiler.lua @@ -96,6 +96,7 @@ local function start_node(pos) 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) end end end @@ -105,14 +106,14 @@ local function node_timer(pos, elapsed) nvm.liquid = nvm.liquid or {} nvm.liquid.amount = nvm.liquid.amount or 0 - power.consumer_alive(pos, nvm) + power.consumer_alive(pos, Cable, CYCLE_TIME) 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 = 25 -- = 5 pump cycles + nvm.error = 2 -- = 2 pump cycles M(pos):set_string("infotext", S("TA3 Oil Reboiler: blocked")) swap_node(pos, false) return false @@ -135,8 +136,9 @@ local function after_dig_node(pos, oldnode) end local function tubelib2_on_update2(pos, outdir, tlib2, node) - if tlib2 == Pipe then - liquid.update_network(pos, outdir) + print("tubelib2_on_update2", tlib2.tube_type) + if tlib2.tube_type == "pipe2" then + liquid.update_network(pos, outdir, tlib2) else power.update_network(pos, outdir, tlib2) end @@ -196,6 +198,9 @@ minetest.register_node("techage:ta3_reboiler", { 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, @@ -261,6 +266,33 @@ minetest.register_node("techage:ta3_reboiler_on", { Pipe:add_secondary_node_names({"techage:ta3_reboiler", "techage:ta3_reboiler_on"}) Cable:add_secondary_node_names({"techage:ta3_reboiler", "techage:ta3_reboiler_on"}) +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" + else + return "unsupported" + end + end, + on_node_load = function(pos, node) + if node.name == "techage:ta3_reboiler_on" then + play_sound(pos) + end + end, +}) + minetest.register_craft({ output = "techage:ta3_reboiler", recipe = { diff --git a/power/distribution.lua b/power/distribution.lua index d777980..2dbf146 100644 --- a/power/distribution.lua +++ b/power/distribution.lua @@ -126,7 +126,7 @@ function techage.power.power_distribution(network, 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(network.available1, network.available2, network.needed1, network.needed2, network.alive) + --print(network.available1, network.available2, network.needed1, network.needed2, network.alive) -- store results network.on = network.available1 + network.available2 >= network.needed1 diff --git a/sounds/techage_reactor.ogg b/sounds/techage_reactor.ogg index 38d5538f7761452ec72dc99783fc9ccfd73f3352..27329b0699ed631d0604d82fe4da00064102dc59 100644 GIT binary patch delta 6253 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 X81(2basct+-f&NYC>qc=kW@cI^h delta 12890 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