From e1013f21dbe61cc580b83b6d278856c6c8c9ff1f Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Tue, 21 May 2019 00:05:53 +0200 Subject: [PATCH] Rework to a new power model --- basis/command.lua | 2 +- basis/node_states.lua | 4 +- basis/power.lua | 326 -------------------------------------- init.lua | 62 ++++---- power/api.md | 79 +++++++++ power/drive_axle.lua | 16 ++ power/electric_cable.lua | 52 +----- power/junction.lua | 85 ++++++++++ power/junctionbox.lua | 52 ++++++ power/power.lua | 231 +++++++++++++++++++++++++++ steam_engine/boiler.lua | 81 +++++----- steam_engine/cylinder.lua | 60 +++---- steam_engine/firebox.lua | 8 +- steam_engine/flywheel.lua | 97 +++++------- steam_engine/gearbox.lua | 36 ++--- 15 files changed, 629 insertions(+), 562 deletions(-) delete mode 100644 basis/power.lua create mode 100644 power/api.md create mode 100644 power/junction.lua create mode 100644 power/junctionbox.lua create mode 100644 power/power.lua diff --git a/basis/command.lua b/basis/command.lua index 5c7f7aa..324e364 100644 --- a/basis/command.lua +++ b/basis/command.lua @@ -92,7 +92,7 @@ end local function register_lbm(name, nodenames) minetest.register_lbm({ - label = "[Tubelib] Node update", + label = "[TechAge] Node update", name = name.."update", nodenames = nodenames, run_at_every_load = true, diff --git a/basis/node_states.lua b/basis/node_states.lua index 9e9a994..97977af 100644 --- a/basis/node_states.lua +++ b/basis/node_states.lua @@ -175,10 +175,10 @@ end function NodeStates:stop(pos, mem) local state = mem.techage_state if state ~= DEFECT then + mem.techage_state = STOPPED if self.stop_node then self.stop_node(pos, mem, state) end - mem.techage_state = STOPPED if self.node_name_passive then swap_node(pos, self.node_name_passive) end @@ -204,10 +204,10 @@ function NodeStates:start(pos, mem, called_from_on_timer) self:fault(pos, mem) return false end + mem.techage_state = RUNNING if self.start_node then self.start_node(pos, mem, state) end - mem.techage_state = RUNNING mem.techage_countdown = 1 if called_from_on_timer then -- timer has to be stopped once to be able to be restarted diff --git a/basis/power.lua b/basis/power.lua deleted file mode 100644 index 73cf921..0000000 --- a/basis/power.lua +++ /dev/null @@ -1,326 +0,0 @@ ---[[ - - TechAge - ======= - - Copyright (C) 2019 Joachim Stolberg - - LGPLv2.1+ - See LICENSE.txt for more information - - Power consumption for any kind of power distribution network - -]]-- - --- for lazy programmers -local S = function(pos) if pos then return minetest.pos_to_string(pos) end end -local P = minetest.string_to_pos -local M = minetest.get_meta --- Techage Related Data -local TRD = function(pos) return (minetest.registered_nodes[minetest.get_node(pos).name] or {}).techage end -local TRDN = function(node) return (minetest.registered_nodes[node.name] or {}).techage end - --- Used to determine the already passed nodes while power distribution -local Route = {} --- Used to store the power input direction of each node -local PowerInDir = {} - -local function pos_already_reached(pos) - local key = minetest.hash_node_position(pos) - if not Route[key] then - Route[key] = true - return false - end - return true -end - -local SideToDir = {B=1, R=2, F=3, L=4, D=5, U=6} - -local function side_to_dir(pos, side) - local node = minetest.get_node(pos) - local dir = SideToDir[side] - if dir < 5 then - dir = (((dir - 1) + (node.param2 % 4)) % 4) + 1 - end - return dir -end - -function techage.get_pos(pos, side) - local dir = side_to_dir(pos, side) - return tubelib2.get_pos(pos, dir) -end - -function techage.percent(max_val, curr_val) - return math.min(math.ceil(((curr_val or 0) * 100.0) / (max_val or 1.0)), 100) -end - --- Both nodes are from the same power network type? -local function matching_nodes(pos, peer_pos) - local tube_type1 = pos and TRD(pos) and TRD(pos).power_network.tube_type - local tube_type2 = peer_pos and TRD(peer_pos) and TRD(peer_pos).power_network.tube_type - return not tube_type1 or not tube_type2 or tube_type1 == tube_type2 -end - -local function get_power_dir(pos) - local key = minetest.hash_node_position(pos) - if not PowerInDir[key] then - PowerInDir[key] = tubelib2.Turn180Deg[side_to_dir(pos, TRD(pos).power_side or 'L')] - end - return PowerInDir[key] -end - -local power_consumption = nil - -local function call_read_power_consumption(pos, in_dir) - if not pos_already_reached(pos) then - local trd = TRD(pos) - if trd and trd.read_power_consumption then - return trd.read_power_consumption(pos, in_dir) - else - return power_consumption(pos, in_dir) - end - end - return 0 -end - --- Calculate the power consumption on the given network -power_consumption = function(pos, in_dir) - local sum = call_read_power_consumption(pos, in_dir) - --local sum = 0 - local mem = tubelib2.get_mem(pos) - local conn = mem.connections or {} - for _,item in pairs(conn) do - if item.pos then - sum = sum + call_read_power_consumption(item.pos, item.in_dir) - end - end - return sum -end - --- Switch active/passive tube nodes -local function turn_tube_on(pos, out_dir, network, on) - if on then - network:switch_tube_line(pos, out_dir, "on") - else - network:switch_tube_line(pos, out_dir, "off") - end -end - - -local turn_on = nil - -local function call_turn_on(pos, in_dir, sum) - if not pos_already_reached(pos) then - local trd = TRD(pos) - if trd and (not trd.valid_power_dir or trd.valid_power_dir(pos, get_power_dir(pos), in_dir)) then - if trd.turn_on then - trd.turn_on(pos, in_dir, sum) - end - end - -- Needed for junctions which could have a local "turn_on" in addition - turn_on(pos, in_dir, sum) - end -end - --- turn nodes on if sum > 0 -turn_on = function(pos, in_dir, sum) - call_turn_on(pos, in_dir, sum) - local trd = TRD(pos) - local mem = tubelib2.get_mem(pos) - local conn = mem.connections or {} - for out_dir,item in pairs(conn) do - if trd and trd.animated_power_network then - turn_tube_on(pos, out_dir, trd.power_network, sum > 0) - end - if item.pos then - call_turn_on(item.pos, item.in_dir, sum) - end - end -end - - --- Starts the overall power consumption and depending on that turns all nodes on/off -local function start_network_power_consumption(pos, in_dir) - Route = {} - local sum = power_consumption(pos, in_dir) - Route = {} - turn_on(pos, in_dir, sum) -end --- --- Generic API functions --- -techage.power = {} - --- Function uses the standard consumer "turn_on" callback --- Returns true, if node could be started/stopped -function techage.power.start_dedicated_node(pos, out_dir, node_name, sum) - local mem = tubelib2.get_mem(pos) - local conn = mem.connections and mem.connections[out_dir] - if conn then - local node = minetest.get_node(conn.pos) - if node.name == node_name then - local trd = TRD(conn.pos) - if trd and (not trd.valid_power_dir or - trd.valid_power_dir(conn.pos, get_power_dir(conn.pos), conn.in_dir)) then - if trd.turn_on then - return trd.turn_on(conn.pos, conn.in_dir, sum) - end - end - end - end - return false -end - --- --- Generator functions for nodes with one power side (view from the outside) --- -techage.generator = {} - -function techage.generator.after_place_node(pos) - local mem = tubelib2.init_mem(pos) - mem.power_capacity = 0 - TRD(pos).power_network:after_place_node(pos) - return mem -end - -function techage.generator.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir) - -- check if contact side is correct - local mem = tubelib2.get_mem(pos) - local pwr_dir = get_power_dir(pos) - if tubelib2.Turn180Deg[out_dir] == pwr_dir then - if not peer_in_dir or not matching_nodes(pos, peer_pos) then - mem.connections = {} -- del connection - else - -- Generator accept one dir only - mem.connections = {[out_dir] = {pos = peer_pos, in_dir = peer_in_dir}} - end - -- To be called delayed, so that all network connections have been established - minetest.after(0.2, start_network_power_consumption, pos, pwr_dir) - end -end - -function techage.generator.turn_power_on(pos, power_capacity) - local mem = tubelib2.get_mem(pos) - mem.power_capacity = power_capacity - -- Starts the overall power consumption and depending on that turns all nodes on/off - -- To be called delayed, so that the generator state machine can be handled before - minetest.after(0.2, start_network_power_consumption, pos, get_power_dir(pos)) -end - --- Power network callback function -function techage.generator.read_power_consumption(pos, in_dir) - local mem = tubelib2.get_mem(pos) - if in_dir == get_power_dir(pos) then - return mem.power_capacity or 0 - end - return 0 -end - -function techage.generator.after_dig_node(pos, oldnode) - TRDN(oldnode).power_network:after_dig_node(pos) - tubelib2.del_mem(pos) -end - -function techage.generator.formspec_level(mem, sum) - local percent = techage.percent(mem.power_capacity, sum) - return "techage_form_level_bg.png^[lowpart:"..percent..":techage_form_level_fg.png]" -end - -function techage.generator.formspec_battery_capa(max_capa, current_capa) - local percent = techage.percent(max_capa, current_capa) - return "techage_form_level_bg.png^[lowpart:"..percent..":techage_form_level_fg.png]" -end -function techage.generator.formspec_battery_load(mem) - if mem.power_capacity ~= 0 then - if mem.charging then - return "techage_form_level_charge.png]" - elseif mem.unloading then - return "techage_form_level_unload.png]" - end - end - return "techage_form_level_off.png]" -end - - --- --- Distributor functions for nodes with 6 power sides (view from the outside) --- -techage.distributor = {} - -function techage.distributor.after_place_node(pos, placer) - local mem = tubelib2.init_mem(pos) - TRD(pos).power_network:after_place_node(pos) - return mem -end - -function techage.distributor.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir) - local mem = tubelib2.get_mem(pos) - mem.connections = mem.connections or {} - if not peer_in_dir or not matching_nodes(pos, peer_pos) then - mem.connections[out_dir] = nil -- del connection - else - mem.connections[out_dir] = {pos = peer_pos, in_dir = peer_in_dir} - end - -- To be called delayed, so that all network connections have been established - minetest.after(0.2, start_network_power_consumption, pos) -end - --- Needed if the junction consumes power in addition -function techage.distributor.read_power_consumption(pos, in_dir) - return power_consumption(pos, in_dir) - TRD(pos).power_consumption or 0 -end - -function techage.distributor.after_dig_node(pos, oldnode) - TRDN(oldnode).power_network:after_dig_node(pos) - tubelib2.del_mem(pos) -end - --- --- Consumer functions with variable number of power sides (view from the outside) --- -techage.consumer = {} - -function techage.consumer.after_place_node(pos, placer) - local mem = tubelib2.init_mem(pos) - -- Power_dir is in-dir - mem.power_consumption = 0 - TRD(pos).power_network:after_place_node(pos) - return mem -end - -function techage.consumer.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir) - local mem = tubelib2.get_mem(pos) - local pwr_dir = get_power_dir(pos) - mem.connections = mem.connections or {} - local trd = TRD(pos) - -- Check direction - if not trd.valid_power_dir(pos, pwr_dir, tubelib2.Turn180Deg[out_dir]) then return end - if not peer_in_dir or not matching_nodes(pos, peer_pos) then - mem.connections[out_dir] = nil -- del connection - else - mem.connections[out_dir] = {pos = peer_pos, in_dir = peer_in_dir} - end - -- To be called delayed, so that all network connections have been established - minetest.after(0.2, start_network_power_consumption, pos, pwr_dir) -end - -function techage.consumer.turn_power_on(pos, power_consumption) - local mem = tubelib2.get_mem(pos) - mem.power_consumption = power_consumption - -- Starts the overall power consumption and depending on that turns all nodes on/off - -- To be called delayed, so that the consumer state machine can be handled before - minetest.after(0.2, start_network_power_consumption, pos, get_power_dir(pos)) -end - --- Power network callback function -function techage.consumer.read_power_consumption(pos, in_dir) - local mem = tubelib2.get_mem(pos) - -- Check direction - if not TRD(pos).valid_power_dir(pos, get_power_dir(pos), in_dir) then return 0 end - return -(mem.power_consumption or 0) -end - -function techage.consumer.after_dig_node(pos, oldnode) - TRDN(oldnode).power_network:after_dig_node(pos) - tubelib2.del_mem(pos) -end diff --git a/init.lua b/init.lua index 8064429..03d47ac 100644 --- a/init.lua +++ b/init.lua @@ -26,9 +26,7 @@ else dofile(MP.."/basis/lib.lua") -- helper functions dofile(MP.."/basis/gravel_lib.lua") -- ore probability dofile(MP.."/basis/guide.lua") -- construction guide - dofile(MP.."/basis/power.lua") -- power distribution dofile(MP.."/basis/node_states.lua") -- state model - dofile(MP.."/basis/junction.lua") -- network junction box dofile(MP.."/basis/tubes.lua") -- tubelib replacement dofile(MP.."/basis/command.lua") -- tubelib replacement dofile(MP.."/basis/consumer.lua") -- consumer base model @@ -46,10 +44,13 @@ else dofile(MP.."/nodes/usmium.lua") -- Power networks + dofile(MP.."/power/power.lua") + dofile(MP.."/power/junction.lua") dofile(MP.."/power/drive_axle.lua") dofile(MP.."/power/steam_pipe.lua") dofile(MP.."/power/biogas_pipe.lua") dofile(MP.."/power/electric_cable.lua") + dofile(MP.."/power/junctionbox.lua") -- Iron Age dofile(MP.."/iron_age/main.lua") @@ -77,36 +78,43 @@ else dofile(MP.."/steam_engine/gearbox.lua") -- Basic Machines - dofile(MP.."/basic_machines/source.lua") - dofile(MP.."/basic_machines/pusher.lua") - dofile(MP.."/basic_machines/blackhole.lua") - dofile(MP.."/basic_machines/legacy_nodes.lua") - dofile(MP.."/basic_machines/grinder.lua") - dofile(MP.."/basic_machines/distributor.lua") - dofile(MP.."/basic_machines/gravelsieve.lua") - dofile(MP.."/basic_machines/gravelrinser.lua") - dofile(MP.."/basic_machines/chest.lua") - dofile(MP.."/basic_machines/autocrafter.lua") - dofile(MP.."/basic_machines/mark.lua") - dofile(MP.."/basic_machines/forceload.lua") - dofile(MP.."/basic_machines/electronic_fab.lua") - if techage.basalt_stone_enabled then - dofile(MP.."/basic_machines/basalt.lua") - end +-- dofile(MP.."/basic_machines/source.lua") +-- dofile(MP.."/basic_machines/pusher.lua") +-- dofile(MP.."/basic_machines/blackhole.lua") +-- dofile(MP.."/basic_machines/legacy_nodes.lua") +-- dofile(MP.."/basic_machines/grinder.lua") +-- dofile(MP.."/basic_machines/distributor.lua") +-- dofile(MP.."/basic_machines/gravelsieve.lua") +-- dofile(MP.."/basic_machines/gravelrinser.lua") +-- dofile(MP.."/basic_machines/chest.lua") +-- dofile(MP.."/basic_machines/autocrafter.lua") +-- dofile(MP.."/basic_machines/mark.lua") +-- dofile(MP.."/basic_machines/forceload.lua") +-- dofile(MP.."/basic_machines/electronic_fab.lua") +-- if techage.basalt_stone_enabled then +-- dofile(MP.."/basic_machines/basalt.lua") +-- end -- Coal power station - dofile(MP.."/coal_power_station/help.lua") - dofile(MP.."/coal_power_station/firebox.lua") - dofile(MP.."/coal_power_station/boiler_base.lua") - dofile(MP.."/coal_power_station/boiler_top.lua") - 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/akkubox.lua") +-- dofile(MP.."/coal_power_station/help.lua") +-- dofile(MP.."/coal_power_station/firebox.lua") +-- dofile(MP.."/coal_power_station/boiler_base.lua") +-- dofile(MP.."/coal_power_station/boiler_top.lua") +-- 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/akkubox.lua") +-- dofile(MP.."/power2/electric_cable.lua") +-- dofile(MP.."/power2/power2.lua") +-- dofile(MP.."/power2/junction.lua") -- network junction box +-- dofile(MP.."/power2/junctionbox.lua") -- network junction box +-- dofile(MP.."/power2/lamp.lua") +-- dofile(MP.."/power2/generator.lua") +-- dofile(MP.."/power2/akkubox.lua") --dofile(MP.."/test/generator.lua") - dofile(MP.."/test/lamp.lua") + --dofile(MP.."/test/lamp.lua") -- dofile(MP.."/test/consumer.lua") --dofile(MP.."/test/consumer2.lua") --dofile(MP.."/test/test.lua") diff --git a/power/api.md b/power/api.md new file mode 100644 index 0000000..6bafd16 --- /dev/null +++ b/power/api.md @@ -0,0 +1,79 @@ +# Power Distribution API + +The module power supports 3 kinds of devices: +- Generators: Provide power, can be turned on/off +- Consumers: Need power, like machines or lamps, can be turned on/off +- Batteries: Can provide stored power, combination of generator and consumer + +### Possible connection sides +``` + U(p) B(ack) + | / + | / + +--|-----+ + / o /| + +--------+ | + L(eft) ----| |o---- R(ight) + | o | + + | / |/ + +--/-----+ + / | + F(ront) | + | + D(own) +``` + +All 3 kinds of nodes use the same registration function to enrich the nodes functionality for power distribution. + + techage.power.register_nodes(names, definition) + -- names is a list of node names + -- definition is a table according to: + + { + on_power_pass1 = func(pos, mem), -- for power balance calculation + on_power_pass2 = func(pos, mem, sum), -- for power balance adjustment + on_power_pass3 = func(pos, mem, sum), -- for power balance result + conn_sides = , -- allowed connection sides for power cables + -- one or several of {"L", "R", "U", "D", "F", "B"} + power_network = , + } + +**Pass1: Power balance calculation** `on_power_pass1` +Return the currently needed amount of power. +For batteries, switch to uncharging and return the uncharging value (negative value). + +**Pass2: Power balance adjustment** `on_power_pass2` +Provides the current power balance. A positive sum means, more power available then needed. +A battery can turn off or even switch to charging if the balance is positive. +In this case, return the correction value (a positive value) instead of 0. +In case of a consumer: turn off if power balance is negative and return the correction value (a negative value). + +**Pass3: Power balance result** `on_power_pass3` +Function provides the final power balance for output purposes. + + + techage.power.power_distribution(pos) + -- Trigger the recalculation or the power distribution in case of + -- a turn on/off request + + + techage.power.formspec_power_bar(max_power, current_power) + -- returns the formspec PGN with a bar according the the ratio `current_power/max_power` + + techage.power.formspec_load_bar(charging) + -- returns the formspec PGN with the charging/uncharging symbol + -- charging can be: + -- true => charging + -- false => uncharging + -- nil => turned off + + +### Internas +The function `techage.power.register_nodes`: +- adds a wrapper to `after_place_node` (needed to maintain tubelib2 data base) +- adds a wrapper to `after_dig_node` (needed to maintain tubelib2 data base) +- adds the function `after_tube_update` (needed to maintain tubelib2 data base) +- adds the table `power` to the node definition with the provided attributes +- adds `power_dirs` to the node meta table with the `conn_sides` information converted to node specific dirs +- adds `mem.connections` for the available power connections with consideration of valid `power_dirs` + diff --git a/power/drive_axle.lua b/power/drive_axle.lua index 2f5502c..980f22c 100644 --- a/power/drive_axle.lua +++ b/power/drive_axle.lua @@ -185,3 +185,19 @@ minetest.register_craft({ {"default:wood", "", "default:junglewood"}, }, }) + + +-- Axles PNG animation +function techage.switch_axles(pos, on) + local s = M(pos):get_string("power_dirs") + if s ~= "" then + for _,indir in ipairs(minetest.deserialize(s)) do + local out_dir = tubelib2.Turn180Deg[indir] + if on then + Axle:switch_tube_line(pos, out_dir, "on") + else + Axle:switch_tube_line(pos, out_dir, "off") + end + end + end +end \ No newline at end of file diff --git a/power/electric_cable.lua b/power/electric_cable.lua index b1a04bb..ab8c77e 100644 --- a/power/electric_cable.lua +++ b/power/electric_cable.lua @@ -8,7 +8,7 @@ LGPLv2.1+ See LICENSE.txt for more information - TA3/TA4 Cable and junction box for electrical power distribution + TA3/TA4 Cable for electrical power distribution ]]-- @@ -25,7 +25,6 @@ local Cable = tubelib2.Tube:new({ dirs_to_check = {1,2,3,4,5,6}, max_tube_length = 1000, show_infotext = false, - --force_to_use_tubes = true, tube_type = "electric_cable", primary_node_names = {"techage:electric_cableS", "techage:electric_cableA"}, secondary_node_names = {}, @@ -47,10 +46,6 @@ function Cable:is_primary_node(pos, dir) return techage.is_primary_node(pos, dir) end -Cable:register_on_tube_update(function(node, pos, out_dir, peer_pos, peer_in_dir) - minetest.registered_nodes[node.name].after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir) -end) - minetest.register_node("techage:electric_cableS", { description = I("TA Electric Cable"), @@ -133,40 +128,9 @@ minetest.register_node("techage:electric_cableA", { drop = "techage:electric_cableS", }) - - -local distributor = techage.distributor - -local size = 3/32 -local Boxes = { - {{-size, -size, size, size, size, 0.5 }}, -- z+ - {{-size, -size, -size, 0.5, size, size}}, -- x+ - {{-size, -size, -0.5, size, size, size}}, -- z- - {{-0.5, -size, -size, size, size, size}}, -- x- - {{-size, -0.5, -size, size, size, size}}, -- y- - {{-size, -size, -size, size, 0.5, size}}, -- y+ -} - -techage.register_junction("techage:electric_junction", 2/8, Boxes, Cable, { - description = I("TA Electricity Junction Box"), - tiles = {"techage_electric_junction.png"}, - groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, techage_trowel = 1}, - sounds = default.node_sound_defaults(), - techage = { - read_power_consumption = distributor.read_power_consumption, - power_network = techage.ElectricCable, - power_consumption = 0, - }, - after_place_node = distributor.after_place_node, - after_dig_node = distributor.after_dig_node, - - after_tube_update = function(node, pos, out_dir, peer_pos, peer_in_dir) - distributor.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir) - local mem = tubelib2.get_mem(pos) - local name = "techage:electric_junction"..techage.junction_type(mem.connections) - minetest.swap_node(pos, {name = name, param2 = 0}) - end, - }) +Cable:register_on_tube_update(function(node, pos, out_dir, peer_pos, peer_in_dir) + minetest.registered_nodes[node.name].after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir) +end) minetest.register_craft({ output = "techage:electric_cableS 6", @@ -177,11 +141,3 @@ minetest.register_craft({ }, }) -minetest.register_craft({ - output = "techage:electric_junction0 2", - recipe = { - {"", "basic_materials:plastic_sheet", ""}, - {"basic_materials:plastic_sheet", "default:copper_ingot", "basic_materials:plastic_sheet"}, - {"", "basic_materials:plastic_sheet", ""}, - }, -}) diff --git a/power/junction.lua b/power/junction.lua new file mode 100644 index 0000000..61e7709 --- /dev/null +++ b/power/junction.lua @@ -0,0 +1,85 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + Junction for power distribution + +]]-- + +-- for lazy programmers +local S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local P = minetest.string_to_pos +local M = minetest.get_meta + + +local function bit(p) + return 2 ^ (p - 1) -- 1-based indexing +end + +-- Typical call: if hasbit(x, bit(3)) then ... +local function hasbit(x, p) + return x % (p + p) >= p +end + +local function setbit(x, p) + return hasbit(x, p) and x or x + p +end + +local function get_node_box(val, size, boxes) + local fixed = {{-size, -size, -size, size, size, size}} + for i = 1,6 do + if hasbit(val, bit(i)) then + for _,box in ipairs(boxes[i]) do + table.insert(fixed, box) + end + end + end + return { + type = "fixed", + fixed = fixed, + } +end + +-- 'size' is the size of the junction cube without any connection, e.g. 1/8 +-- 'boxes' is a table with 6 table elements for the 6 possible connection arms +-- 'network' is the tubelib2 instance +-- 'node' is the node definition with tiles, callback functions, and so on +function techage.register_junction(name, size, boxes, network, node) + for idx = 0,63 do + local ndef = table.copy(node) + if idx == 0 then + ndef.groups.not_in_creative_inventory = 0 + else + ndef.groups.not_in_creative_inventory = 1 + end + ndef.groups.techage_trowel = 1 + ndef.drawtype = "nodebox" + ndef.node_box = get_node_box(idx, size, boxes) + ndef.paramtype2 = "facedir" + ndef.on_rotate = screwdriver.disallow + ndef.paramtype = "light" + ndef.sunlight_propagates = true + ndef.is_ground_content = false + ndef.drop = name.."0" + minetest.register_node(name..idx, ndef) + -- Register in addition for power distribution + techage.power.register_node({name..idx}, {power_network = network}) + end +end + +function techage.junction_type(pos, network) + local val = 0 + for dir = 1,6 do + if network:connected(pos, dir) then + val = setbit(val, bit(dir)) + end + end + return val +end + diff --git a/power/junctionbox.lua b/power/junctionbox.lua new file mode 100644 index 0000000..d184201 --- /dev/null +++ b/power/junctionbox.lua @@ -0,0 +1,52 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + TA3/TA4 Junction box for electrical power distribution + +]]-- + +-- for lazy programmers +local M = minetest.get_meta + +-- Load support for intllib. +local MP = minetest.get_modpath("techage") +local I,_ = dofile(MP.."/intllib.lua") + +local size = 3/32 +local Boxes = { + {{-size, -size, size, size, size, 0.5 }}, -- z+ + {{-size, -size, -size, 0.5, size, size}}, -- x+ + {{-size, -size, -0.5, size, size, size}}, -- z- + {{-0.5, -size, -size, size, size, size}}, -- x- + {{-size, -0.5, -size, size, size, size}}, -- y- + {{-size, -size, -size, size, 0.5, size}}, -- y+ +} + +techage.register_junction("techage:electric_junction", 2/8, Boxes, techage.ElectricCable, { + description = I("TA Electric Junction Box"), + tiles = {"techage_electric_junction.png"}, + groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 3, techage_trowel = 1}, + sounds = default.node_sound_defaults(), + + on_construct = tubelib2.init_mem, + after_tube_update = function(node, pos, out_dir, peer_pos, peer_in_dir) + local name = "techage:electric_junction"..techage.junction_type(pos, techage.ElectricCable) + minetest.swap_node(pos, {name = name, param2 = 0}) + end, + }) + +minetest.register_craft({ + output = "techage:electric_junction0 2", + recipe = { + {"", "basic_materials:plastic_sheet", ""}, + {"basic_materials:plastic_sheet", "default:copper_ingot", "basic_materials:plastic_sheet"}, + {"", "basic_materials:plastic_sheet", ""}, + }, +}) \ No newline at end of file diff --git a/power/power.lua b/power/power.lua new file mode 100644 index 0000000..5fe6233 --- /dev/null +++ b/power/power.lua @@ -0,0 +1,231 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019 Joachim Stolberg + + LGPLv2.1+ + See LICENSE.txt for more information + + Power distribution and consumption calculation + for any kind of power distribution network + +]]-- + +-- for lazy programmers +local S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local P = minetest.string_to_pos +local M = minetest.get_meta +-- Techage Related Data +local PWR = function(pos) return (minetest.registered_nodes[minetest.get_node(pos).name] or {}).power end +local PWRN = function(node) return (minetest.registered_nodes[node.name] or {}).power end + +-- Used to determine the already passed nodes while power distribution +local Route = {} + +local function pos_already_reached(pos) + local key = minetest.hash_node_position(pos) + if not Route[key] then + Route[key] = true + return false + end + return true +end + +local SideToDir = {B=1, R=2, F=3, L=4, D=5, U=6} + +local function side_to_dir(param2, side) + local dir = SideToDir[side] + if dir < 5 then + dir = (((dir - 1) + (param2 % 4)) % 4) + 1 + end + return dir +end + +function techage.get_pos(pos, side) + local node = minetest.get_node(pos) + local dir = nil + if node.name ~= "air" and node.name ~= "ignore" then + dir = side_to_dir(node.param2, side) + end + return tubelib2.get_pos(pos, dir) +end + +local function set_conn_dirs(pos, sides) + local tbl = {} + local node = minetest.get_node(pos) + for _,side in ipairs(sides) do + tbl[#tbl+1] = tubelib2.Turn180Deg[side_to_dir(node.param2, side)] + end + M(pos):set_string("power_dirs", minetest.serialize(tbl)) +end + +local function valid_indir(pos, in_dir) + local s = M(pos):get_string("power_dirs") + if s == "" then + local pwr = PWR(pos) + if pwr then + set_conn_dirs(pos, pwr.conn_sides) + end + end + if s ~= "" then + local tbl + for _,dir in ipairs(minetest.deserialize(s)) do + if dir == in_dir then + return true + end + end + end + return false +end + +local function valid_outdir(pos, out_dir) + return valid_indir(pos, tubelib2.Turn180Deg[out_dir]) +end + +-- Both nodes are from the same power network type? +local function matching_nodes(pos, peer_pos) + local tube_type1 = pos and PWR(pos) and PWR(pos).power_network.tube_type + local tube_type2 = peer_pos and PWR(peer_pos) and PWR(peer_pos).power_network.tube_type + return not tube_type1 or not tube_type2 or tube_type1 == tube_type2 +end + +local function get_clbk(pos, clbk_name) + local pwr = PWR(pos) + return pwr and pwr[clbk_name] +end + +local function connection_walk(pos, clbk_name, sum) + local clbk = get_clbk(pos, clbk_name) + --print("connection_walk", S(pos), sum, clbk) + if clbk then + local mem = tubelib2.get_mem(pos) + sum = sum - (clbk(pos, mem, sum) or 0) + end + local mem = tubelib2.get_mem(pos) + for _,item in pairs(mem.connections or {}) do + if item.pos and not pos_already_reached(item.pos) then + sum = connection_walk(item.pos, clbk_name, sum) + end + end + return sum +end + +-- Start the overall power consumption and depending on that +-- turn nodes on/off +local function power_distribution(pos) + local sum = 0 + Route = {} + pos_already_reached(pos) + sum = connection_walk(pos, "on_power_pass1", sum) + Route = {} + pos_already_reached(pos) + sum = connection_walk(pos, "on_power_pass2", sum) + Route = {} + pos_already_reached(pos) + sum = connection_walk(pos, "on_power_pass3", sum) + print("power sum = "..sum) +end + +local function register_lbm(name) + minetest.register_lbm({ + label = "[TechAge] Node update", + nodenames = {name}, + name = name.."_update", + run_at_every_load = true, + action = function(pos, node) + local pwr = PWRN(node) + -- repair power_dirs + if pwr and pwr.conn_sides and M(pos):get_string("power_dirs") == "" then + set_conn_dirs(pos, pwr.conn_sides) + end + end + }) +end + +-- +-- Generic API functions +-- +techage.power = {} + +techage.power.power_distribution = power_distribution + +function techage.power.register_node(names, pwr_def) + for _,name in ipairs(names) do + local ndef = minetest.registered_nodes[name] + if ndef then + minetest.override_item(name, { + power = { + on_power_pass1 = pwr_def.on_power_pass1, + on_power_pass2 = pwr_def.on_power_pass2, + on_power_pass3 = pwr_def.on_power_pass3, + conn_sides = pwr_def.conn_sides or {"L", "R", "U", "D", "F", "B"}, + power_network = pwr_def.power_network, + after_place_node = ndef.after_place_node, + after_dig_node = ndef.after_dig_node, + after_tube_update = ndef.after_tube_update, + }, + -- after_place_node decorator + after_place_node = function(pos, placer, itemstack, pointed_thing) + local pwr = PWR(pos) + set_conn_dirs(pos, pwr.conn_sides) + pwr.power_network:after_place_node(pos) + if pwr.after_place_node then + return pwr.after_place_node(pos, placer, itemstack, pointed_thing) + end + end, + -- after_dig_node decorator + after_dig_node = function(pos, oldnode, oldmetadata, digger) + local pwr = PWRN(oldnode) + pwr.power_network:after_dig_node(pos) + minetest.after(0.1, tubelib2.del_mem, pos) -- At latest... + if pwr.after_dig_node then + return pwr.after_dig_node(pos, oldnode, oldmetadata, digger) + end + end, + -- tubelib2 callback, called after any connection change + after_tube_update = function(node, pos, out_dir, peer_pos, peer_in_dir) + local pwr = PWR(pos) + local mem = tubelib2.get_mem(pos) + mem.connections = mem.connections or {} + if not peer_pos or not valid_indir(peer_pos, peer_in_dir) + or not valid_outdir(pos, out_dir) + or not matching_nodes(pos, peer_pos) then + mem.connections[out_dir] = nil -- del connection + else + mem.connections[out_dir] = {pos = peer_pos, in_dir = peer_in_dir} + end + -- To be called delayed, so that all network connections have been established + minetest.after(0.2, power_distribution, pos) + if pwr.after_tube_update then + return pwr.after_tube_update(node, pos, out_dir, peer_pos, peer_in_dir) + end + end, + }) + pwr_def.power_network:add_secondary_node_names({name}) + register_lbm(name) + end + end +end + +function techage.power.percent(max_val, curr_val) + return math.min(math.ceil(((curr_val or 0) * 100.0) / (max_val or 1.0)), 100) +end + +function techage.power.formspec_power_bar(max_power, current_power) + local percent = techage.power.percent(max_power, current_power) + return "techage_form_level_bg.png^[lowpart:"..percent..":techage_form_level_fg.png" +end + +-- charging is true, false, or nil if turned off +function techage.power.formspec_load_bar(charging) + if charging ~= nil then + if charging then + return "techage_form_level_charge.png" + else + return "techage_form_level_unload.png" + end + end + return "techage_form_level_off.png" +end diff --git a/steam_engine/boiler.lua b/steam_engine/boiler.lua index 7501055..c74ddcd 100644 --- a/steam_engine/boiler.lua +++ b/steam_engine/boiler.lua @@ -30,7 +30,6 @@ local MAX_WATER = 10 local POWER_CAPACITY = 10 local Pipe = techage.SteamPipe -local generator = techage.generator local Water = { @@ -53,7 +52,7 @@ local function formspec(self, pos, mem) "image[1,1.6;1,1;techage_form_mask.png]".. "image[2,0.5;1,2;techage_form_temp_bg.png^[lowpart:".. temp..":techage_form_temp_fg.png]".. - "image[7,0.5;1,2;"..generator.formspec_level(mem, mem.power_result).. + "image[7,0.5;1,2;"..techage.power.formspec_power_bar(POWER_CAPACITY, mem.power_result).."]".. "image_button[6,1;1,1;".. self:get_state_button_image(mem) ..";state_button;]".. "button[3,1.5;2,1;update;"..I("Update").."]".. "list[current_player;main;0,3;8,4;]".. @@ -67,11 +66,11 @@ local function can_start(pos, mem, state) end local function start_node(pos, mem, state) - generator.turn_power_on(pos, POWER_CAPACITY) + techage.power.power_distribution(pos) end local function stop_node(pos, mem, state) - generator.turn_power_on(pos, 0) + techage.power.power_distribution(pos) end local State = techage.NodeStates:new({ @@ -85,6 +84,25 @@ local State = techage.NodeStates:new({ stop_node = stop_node, }) + +-- Pass1: Power balance calculation +local function on_power_pass1(pos, mem) + if State:is_active(mem) then + return -POWER_CAPACITY + end + return 0 +end + +-- Pass2: Power balance adjustment +local function on_power_pass2(pos, mem, sum) + return 0 +end + +-- Pass3: Power balance result +local function on_power_pass3(pos, mem, sum) + mem.power_result = sum +end + local function get_water(pos) local inv = M(pos):get_inventory() local items = inv:get_stack("water", 1) @@ -138,18 +156,6 @@ local function node_timer(pos, elapsed) return mem.temperature > 20 end -local function turn_power_on(pos, in_dir, sum) - local mem = tubelib2.get_mem(pos) - -- store result for formspec - mem.power_result = sum - if State:is_active(mem) and sum <= 0 then - State:fault(pos, mem) - -- No automatic turn on - mem.power_capacity = 0 - end - M(pos):set_string("formspec", formspec(State, pos, mem)) -end - local function on_receive_fields(pos, formname, fields, player) if minetest.is_protected(pos, player:get_player_name()) then return @@ -158,11 +164,13 @@ local function on_receive_fields(pos, formname, fields, player) State:state_button_event(pos, mem, fields) if fields.update then + if mem.temperature > 20 then + minetest.get_node_timer(pos):start(CYCLE_TIME) + end M(pos):set_string("formspec", formspec(State, pos, mem)) end end - local function on_rightclick(pos) local mem = tubelib2.get_mem(pos) M(pos):set_string("formspec", formspec(State, pos, mem)) @@ -231,7 +239,6 @@ minetest.register_node("techage:boiler1", { fixed = {-8/32, -16/32, -8/32, 8/32, 16/32, 8/32}, }, - --paramtype2 = "facedir", groups = {cracky=1}, on_rotate = screwdriver.disallow, is_ground_content = false, @@ -256,28 +263,15 @@ minetest.register_node("techage:boiler2", { on_receive_fields = on_receive_fields, on_rightclick = on_rightclick, - techage = { - turn_on = turn_power_on, - read_power_consumption = generator.read_power_consumption, - power_network = Pipe, - signal_heat = function(pos) - local mem = tubelib2.get_mem(pos) - mem.fire_trigger = true - if not minetest.get_node_timer(pos):is_started() then - minetest.get_node_timer(pos):start(CYCLE_TIME) - end - end, - power_side = "U", - }, - on_construct = function(pos) + tubelib2.init_mem(pos) local inv = M(pos):get_inventory() inv:set_size('water', 1) inv:set_size('input', 1) end, after_place_node = function(pos, placer) - local mem = generator.after_place_node(pos) + local mem = tubelib2.get_mem(pos) State:node_init(pos, mem, "") local node = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}) if node.name == "techage:boiler1" then @@ -287,16 +281,20 @@ minetest.register_node("techage:boiler2", { after_dig_node = function(pos, oldnode, oldmetadata, digger) State:after_dig_node(pos, oldnode, oldmetadata, digger) - generator.after_dig_node(pos, oldnode) end, - after_tube_update = generator.after_tube_update, - on_metadata_inventory_put = function(pos) minetest.after(0.5, move_to_water, pos) end, - --paramtype2 = "facedir", + power_signal_heat = function(pos) + local mem = tubelib2.get_mem(pos) + mem.fire_trigger = true + if not minetest.get_node_timer(pos):is_started() then + minetest.get_node_timer(pos):start(CYCLE_TIME) + end + end, + drop = "", groups = {cracky=1}, on_rotate = screwdriver.disallow, @@ -304,6 +302,15 @@ minetest.register_node("techage:boiler2", { sounds = default.node_sound_metal_defaults(), }) +techage.power.register_node({"techage:boiler2"}, { + on_power_pass1 = on_power_pass1, + on_power_pass2 = on_power_pass2, + on_power_pass3 = on_power_pass3, + conn_sides = {"U"}, + power_network = Pipe, +}) + + minetest.register_craft({ output = "techage:boiler1", recipe = { diff --git a/steam_engine/cylinder.lua b/steam_engine/cylinder.lua index e43e594..1c11b3b 100644 --- a/steam_engine/cylinder.lua +++ b/steam_engine/cylinder.lua @@ -24,7 +24,6 @@ local I,_ = dofile(MP.."/intllib.lua") local POWER_CONSUMPTION = 8 local Pipe = techage.SteamPipe -local consumer = techage.consumer local function swap_node(pos, name) local node = minetest.get_node(pos) @@ -35,30 +34,27 @@ local function swap_node(pos, name) minetest.swap_node(pos, node) end --- called from pipe network -local function valid_power_dir(pos, power_dir, in_dir) - return power_dir == in_dir -end - --- called from pipe network -local function turn_power_on_clbk(pos, in_dir, sum) - local mem = tubelib2.get_mem(pos) - -- Simply store state to be prepared, when flywheel wants to start. - mem.running = sum > 0 +local function on_power_pass1(pos, mem) + return POWER_CONSUMPTION end + +local function on_power_pass2(pos, mem, sum) + mem.running = sum > 0 + return 0 +end -- called from flywheel local function start_cylinder(pos, on) local mem = tubelib2.get_mem(pos) if on and mem.running then - consumer.turn_power_on(pos, POWER_CONSUMPTION) swap_node(pos, "techage:cylinder_on") + techage.power.power_distribution(pos) return true else - consumer.turn_power_on(pos, 0) swap_node(pos, "techage:cylinder") + techage.power.power_distribution(pos) + return false end - return false end @@ -73,24 +69,10 @@ minetest.register_node("techage:cylinder", { "techage_filling_ta2.png^techage_cylinder.png^techage_frame_ta2.png", "techage_filling_ta2.png^techage_cylinder.png^techage_frame_ta2.png", }, - techage = { - turn_on = turn_power_on_clbk, - read_power_consumption = consumer.read_power_consumption, - power_network = Pipe, - power_side = "L", - valid_power_dir = valid_power_dir, - start_cylinder = start_cylinder, - }, - after_place_node = function(pos, placer) - local mem = consumer.after_place_node(pos, placer) - mem.power_consume = 0 -- needed power to run - mem.power_supply = false -- power available? - end, + on_construct = tubelib2.init_mem, + start_cylinder = start_cylinder, - after_tube_update = consumer.after_tube_update, - after_dig_node = consumer.after_dig_node, - paramtype2 = "facedir", groups = {cracky=2, crumbly=2, choppy=2}, on_rotate = screwdriver.disallow, @@ -127,17 +109,8 @@ minetest.register_node("techage:cylinder_on", { }, }, }, - techage = { - turn_on = turn_power_on_clbk, - read_power_consumption = consumer.read_power_consumption, - power_network = Pipe, - power_side = "L", - valid_power_dir = valid_power_dir, - start_cylinder = start_cylinder, - }, - after_tube_update = consumer.after_tube_update, - after_dig_node = consumer.after_dig_node, + start_cylinder = start_cylinder, paramtype2 = "facedir", groups = {not_in_creative_inventory=1}, @@ -147,6 +120,13 @@ minetest.register_node("techage:cylinder_on", { sounds = default.node_sound_wood_defaults(), }) +techage.power.register_node({"techage:cylinder", "techage:cylinder_on"}, { + on_power_pass1 = on_power_pass1, + on_power_pass2 = on_power_pass2, + conn_sides = {"L"}, + power_network = Pipe, +}) + minetest.register_craft({ output = "techage:cylinder", recipe = { diff --git a/steam_engine/firebox.lua b/steam_engine/firebox.lua index c09f601..e5b3ad9 100644 --- a/steam_engine/firebox.lua +++ b/steam_engine/firebox.lua @@ -16,8 +16,6 @@ local S = function(pos) if pos then return minetest.pos_to_string(pos) end end local P = minetest.string_to_pos local M = minetest.get_meta --- Techage Related Data -local TRD = function(pos) return (minetest.registered_nodes[minetest.get_node(pos).name] or {}).techage end -- Load support for intllib. local MP = minetest.get_modpath("techage") @@ -31,9 +29,9 @@ local CYCLE_TIME = 2 local function node_timer(pos, elapsed) local mem = tubelib2.get_mem(pos) if mem.running then - local trd = TRD({x=pos.x, y=pos.y+2, z=pos.z}) - if trd and trd.signal_heat then - trd.signal_heat({x=pos.x, y=pos.y+2, z=pos.z}) + local ndef = minetest.registered_nodes[minetest.get_node({x=pos.x, y=pos.y+2, z=pos.z}).name] + if ndef and ndef.power_signal_heat then + ndef.power_signal_heat({x=pos.x, y=pos.y+2, z=pos.z}) end mem.burn_cycles = (mem.burn_cycles or 0) - 1 if mem.burn_cycles <= 0 then diff --git a/steam_engine/flywheel.lua b/steam_engine/flywheel.lua index 913f4e9..5f37fdf 100644 --- a/steam_engine/flywheel.lua +++ b/steam_engine/flywheel.lua @@ -16,8 +16,6 @@ local S = function(pos) if pos then return minetest.pos_to_string(pos) end end local P = minetest.string_to_pos local M = minetest.get_meta --- Techage Related Data -local TRD = function(pos) return (minetest.registered_nodes[minetest.get_node(pos).name] or {}).techage end -- Load support for intllib. local MP = minetest.get_modpath("techage") @@ -29,14 +27,13 @@ local CYCLE_TIME = 8 local POWER_CAPACITY = 25 local Axle = techage.Axle -local generator = techage.generator local function formspec(self, pos, mem) return "size[8,7]".. default.gui_bg.. default.gui_bg_img.. default.gui_slots.. - "image[6,0.5;1,2;"..generator.formspec_level(mem, mem.power_result).. + "image[6,0.5;1,2;"..techage.power.formspec_power_bar(POWER_CAPACITY, mem.power_result).."]".. "image_button[5,1;1,1;".. self:get_state_button_image(mem) ..";state_button;]".. "button[2,1.5;2,1;update;"..I("Update").."]".. "list[current_player;main;0,3;8,4;]".. @@ -51,9 +48,9 @@ local function start_cylinder(pos, on, mem) end end local pos2 = techage.get_pos(pos, 'L') - local trd = TRD(pos2) - if trd and trd.start_cylinder then - return trd.start_cylinder(pos2, on, mem) + local ndef = minetest.registered_nodes[minetest.get_node(pos2).name] + if ndef and ndef.start_cylinder then + return ndef.start_cylinder(pos2, on) end return false end @@ -74,15 +71,17 @@ local function play_sound(pos) end local function start_node(pos, mem, state) - generator.turn_power_on(pos, POWER_CAPACITY) - mem.techage_state = techage.RUNNING - play_sound(pos) + techage.power.power_distribution(pos) + if mem.power_result > 0 then + techage.switch_axles(pos, true) + play_sound(pos) + end end local function stop_node(pos, mem, state) - mem.techage_state = techage.STOPPED start_cylinder(pos, false, mem) - generator.turn_power_on(pos, 0) + techage.power.power_distribution(pos) + techage.switch_axles(pos, false) end local State = techage.NodeStates:new({ @@ -96,13 +95,31 @@ local State = techage.NodeStates:new({ stop_node = stop_node, }) +-- Pass1: Power balance calculation +local function on_power_pass1(pos, mem) + if State:is_active(mem) then + return -POWER_CAPACITY + end + return 0 +end + +-- Pass2: Power balance adjustment +local function on_power_pass2(pos, mem, sum) + return 0 +end + +-- Pass3: Power balance result +local function on_power_pass3(pos, mem, sum) + mem.power_result = sum +end + local function distibuting(pos, mem) if mem.power_result > 0 then State:keep_running(pos, mem, COUNTDOWN_TICKS) else State:fault(pos, mem) start_cylinder(pos, false, mem) - generator.turn_power_on(pos, 0) + techage.power.power_distribution(pos) end end @@ -114,28 +131,11 @@ local function node_timer(pos, elapsed) else State:fault(pos, mem) start_cylinder(pos, false, mem) - generator.turn_power_on(pos, 0) + techage.power.power_distribution(pos) end return State:is_active(mem) end -local function valid_power_dir(pos, power_dir, in_dir) - return power_dir == in_dir -end - -local function turn_power_on(pos, in_dir, sum) - local mem = tubelib2.get_mem(pos) - -- store result for formspec - mem.power_result = sum - if State:is_active(mem) and sum <= 0 then - State:fault(pos, mem) - start_cylinder(pos, false, mem) - -- No automatic turn on - mem.power_capacity = 0 - end - M(pos):set_string("formspec", formspec(State, pos, mem)) -end - local function on_receive_fields(pos, formname, fields, player) if minetest.is_protected(pos, player:get_player_name()) then return @@ -164,26 +164,19 @@ minetest.register_node("techage:flywheel", { "techage_filling_ta2.png^techage_frame_ta2.png^techage_flywheel.png", "techage_filling_ta2.png^techage_frame_ta2.png^techage_flywheel.png^[transformFX]", }, - techage = { - turn_on = turn_power_on, - read_power_consumption = generator.read_power_consumption, - power_network = Axle, - power_side = "R", - animated_power_network = true, - }, + + on_construct = tubelib2.init_mem, after_place_node = function(pos, placer) - local mem = generator.after_place_node(pos) + local mem = tubelib2.get_mem(pos) State:node_init(pos, mem, "") on_rightclick(pos) end, after_dig_node = function(pos, oldnode, oldmetadata, digger) State:after_dig_node(pos, oldnode, oldmetadata, digger) - generator.after_dig_node(pos, oldnode) end, - after_tube_update = generator.after_tube_update, on_receive_fields = on_receive_fields, on_rightclick = on_rightclick, on_timer = node_timer, @@ -234,20 +227,7 @@ minetest.register_node("techage:flywheel_on", { }, }, }, - techage = { - turn_on = turn_power_on, - read_power_consumption = generator.read_power_consumption, - power_network = Axle, - power_side = "R", - animated_power_network = true, - }, - after_dig_node = function(pos, oldnode, oldmetadata, digger) - State:after_dig_node(pos, oldnode, oldmetadata, digger) - generator.after_dig_node(pos, oldnode) - end, - - after_tube_update = generator.after_tube_update, on_receive_fields = on_receive_fields, on_rightclick = on_rightclick, on_timer = node_timer, @@ -261,6 +241,14 @@ minetest.register_node("techage:flywheel_on", { sounds = default.node_sound_wood_defaults(), }) +techage.power.register_node({"techage:flywheel", "techage:flywheel_on"}, { + on_power_pass1 = on_power_pass1, + on_power_pass2 = on_power_pass2, + on_power_pass3 = on_power_pass3, + conn_sides = {"R"}, + power_network = Axle, +}) + minetest.register_craft({ output = "techage:flywheel", recipe = { @@ -277,6 +265,7 @@ minetest.register_lbm({ run_at_every_load = true, action = function(pos, node) play_sound(pos) + minetest.get_node_timer(pos):start(CYCLE_TIME) end }) diff --git a/steam_engine/gearbox.lua b/steam_engine/gearbox.lua index bddcd85..8a884e4 100644 --- a/steam_engine/gearbox.lua +++ b/steam_engine/gearbox.lua @@ -24,7 +24,6 @@ local I,_ = dofile(MP.."/intllib.lua") local POWER_CONSUMPTION = 1 local Axle = techage.Axle -local distributor = techage.distributor local function swap_node(pos, name) local node = minetest.get_node(pos) @@ -35,28 +34,25 @@ local function swap_node(pos, name) minetest.swap_node(pos, node) end -local function turn_on(pos, dir, sum) +local function on_power_pass1(pos, mem) + return POWER_CONSUMPTION +end + +local function on_power_pass2(pos, mem, sum) if sum > 0 then swap_node(pos, "techage:gearbox_on") + techage.switch_axles(pos, true) else swap_node(pos, "techage:gearbox") + techage.switch_axles(pos, false) end end minetest.register_node("techage:gearbox", { description = I("TA2 Gearbox"), tiles = {"techage_filling_ta2.png^techage_axle_gearbox.png^techage_frame_ta2.png"}, - techage = { - turn_on = turn_on, - read_power_consumption = distributor.read_power_consumption, - power_network = Axle, - power_consumption = POWER_CONSUMPTION, - animated_power_network = true, - }, - after_place_node = distributor.after_place_node, - after_tube_update = distributor.after_tube_update, - after_dig_node = distributor.after_dig_node, + on_construct = tubelib2.init_mem, paramtype2 = "facedir", groups = {cracky=2, crumbly=2, choppy=2}, @@ -80,16 +76,6 @@ minetest.register_node("techage:gearbox_on", { }, }, }, - techage = { - turn_on = turn_on, - read_power_consumption = distributor.read_power_consumption, - power_network = Axle, - power_consumption = POWER_CONSUMPTION, - animated_power_network = true, - }, - - after_tube_update = distributor.after_tube_update, - after_dig_node = distributor.after_dig_node, paramtype2 = "facedir", groups = {not_in_creative_inventory=1}, @@ -99,6 +85,12 @@ minetest.register_node("techage:gearbox_on", { sounds = default.node_sound_wood_defaults(), }) +techage.power.register_node({"techage:gearbox", "techage:gearbox_on"}, { + on_power_pass1 = on_power_pass1, + on_power_pass2 = on_power_pass2, + power_network = Axle, +}) + minetest.register_craft({ output = "techage:gearbox 2", recipe = {