From 0237d0281e15ba0e12f6aed6f6b79869539e6b8b Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Thu, 3 Jun 2021 15:56:29 +0200 Subject: [PATCH] Add liquid, bug fixes and improvements --- README.md | 18 +- init.lua | 7 +- liquid.lua | 266 ++++++++++++++++++++++ networks.lua | 41 +++- power.lua | 2 + test/test_liquid.lua | 430 ++++++++++++++++++++++++++++++++++++ test/test_power.lua | 10 +- textures/networks_arrow.png | Bin 0 -> 109 bytes textures/networks_pump.png | Bin 0 -> 105 bytes textures/networks_tank.png | Bin 0 -> 101 bytes 10 files changed, 764 insertions(+), 10 deletions(-) create mode 100644 liquid.lua create mode 100644 test/test_liquid.lua create mode 100644 textures/networks_arrow.png create mode 100644 textures/networks_pump.png create mode 100644 textures/networks_tank.png diff --git a/README.md b/README.md index 20fc3b5..9ae751b 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,12 @@ The mod uses a whitelist for filling material. The function ### Liquid Networks -tbd. +Liquid networks consists of following node types: + +- Pumps, nodes pumping liquids from/to tanks +- Tanks, storuing liquids +- Junctions, to connect pipes to networks +- Valves, to turn on/off pipe segments ### Test Nodes @@ -54,6 +59,13 @@ All three nodes can be turned on/off by right-clicking. - a power switch to turn on/off consumers - a tool to hide/open cables and junctions +The file `./test/test_liquid.lua` includes test nodes of each kind of liquid nodes. + +- [P] a pump which pumps 2 items every 2 s +- [T] tree types of tanks (empty, milk, water) +- junction node +- a value to connect/disconnect pipes + ### License @@ -86,3 +98,7 @@ Required: tubelib2 **2021-05-30 V0.05** - Change power API + +**2021-06-03 V0.06** +- Add 'liquid' +- bug fixes and improvements diff --git a/init.lua b/init.lua index b4f87b6..0497e19 100644 --- a/init.lua +++ b/init.lua @@ -13,7 +13,7 @@ networks = {} -- Version for compatibility checks, see readme.md/history -networks.version = 0.05 +networks.version = 0.06 if not minetest.global_exists("tubelib2") or tubelib2.version < 2.1 then minetest.log("error", "[networks] Networks requires tubelib2 version 2.1 or newer!") @@ -26,7 +26,8 @@ dofile(MP .. "/hidden.lua") dofile(MP .. "/networks.lua") dofile(MP .. "/junction.lua") dofile(MP .. "/power.lua") ---dofile(MP .. "/liquid.lua") +dofile(MP .. "/liquid.lua") -- Only for testing/demo purposes -dofile(MP .. "/test/test_power.lua") \ No newline at end of file +dofile(MP .. "/test/test_power.lua") +dofile(MP .. "/test/test_liquid.lua") diff --git a/liquid.lua b/liquid.lua new file mode 100644 index 0000000..0c017e0 --- /dev/null +++ b/liquid.lua @@ -0,0 +1,266 @@ +--[[ + + Networks + ======== + + Copyright (C) 2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + Liquid API for liquid pumping and storing nodes + +]]-- + +-- 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 = tubelib2.get_node_lvm +local LQD = function(pos) return (minetest.registered_nodes[N(pos).name] or {}).liquid end + +networks.liquid = {} + + +-- return list of nodes {pos = ..., indir = ...} of given node_type +local function get_network_table(pos, tlib2, outdir, node_type) + if networks.determine_netID(pos, tlib2, outdir) then + local netw = networks.get_network_table(pos, tlib2, outdir) + if netw then + return netw[node_type] or {} + end + end + return {} +end + +------------------------------------------------------------------------------- +-- For all types of nodes +------------------------------------------------------------------------------- +-- names: list of node names +-- tlib2: tubelib2 instance +-- node_type: one of "pump", "tank", "junc" +-- valid_sides: something like {"L", "R"} or nil +-- liquid_callbacks = { +-- capa = CAPACITY, +-- peek = function(pos, indir), -- returns: liquid name +-- put = function(pos, indir, name, amount), -- returns: liquid leftover or 0 +-- take = function(pos, indir, name, amount), -- returns: taken, name +-- untake = function(pos, indir, name, amount), -- returns: leftover +-- } +function networks.liquid.register_nodes(names, tlib2, node_type, valid_sides, liquid_callbacks) + if node_type == "pump" then + assert(#valid_sides == 1 or #valid_sides == 2) + elseif node_type == "tank" or node_type == "junc" then + assert(not valid_sides or type(valid_sides) == "table") + valid_sides = valid_sides or {"B", "R", "F", "L", "D", "U"} + else + error("parameter error") + end + + if node_type == "tank" then + assert(type(liquid_callbacks) == "table") + end + + tlib2:add_secondary_node_names(names) + + for _, name in ipairs(names) do + local ndef = minetest.registered_nodes[name] + local tbl = ndef.networks or {} + tbl[tlib2.tube_type] = {ntype = node_type} + minetest.override_item(name, {networks = tbl}) + minetest.override_item(name, {liquid = liquid_callbacks}) + tlib2:set_valid_sides(name, valid_sides) + end +end + +-- To be called for each liquid network change via +-- tubelib2_on_update2 or register_on_tube_update2 +function networks.liquid.update_network(pos, outdir, tlib2, node) + local ndef = networks.net_def(pos, tlib2.tube_type) + if ndef.ntype == "junc" then + outdir = 0 + end + networks.update_network(pos, outdir, tlib2, node) +end + +------------------------------------------------------------------------------- +-- Client/pump functions +------------------------------------------------------------------------------- +-- Determine and return liquid 'name' from the +-- remote inventory. +function networks.liquid.peek(pos, tlib2, outdir) + assert(outdir) + for _,item in ipairs(get_network_table(pos, tlib2, outdir, "tank")) do + local liq = LQD(item.pos) + if liq and liq.peek then + return liq.peek(item.pos, item.indir) + end + end +end + +-- Add given amount of liquid to the remote inventory. +-- return leftover amount +function networks.liquid.put(pos, tlib2, outdir, name, amount, show_debug_cube) + assert(outdir) + assert(name) + assert(amount and amount > 0) + for _,item in ipairs(get_network_table(pos, tlib2, outdir, "tank")) do + local liq = LQD(item.pos) + if liq and liq.put and liq.peek then + -- wrong items? + local peek = liq.peek(item.pos, item.indir) + if peek and peek ~= name then return amount or 0 end + if show_debug_cube then + networks.set_marker(item.pos, "put", 1.1, 1) + end + amount = liq.put(item.pos, item.indir, name, amount) + if not amount or amount == 0 then break end + end + end + return amount or 0 +end + +-- Take given amount of liquid from the remote inventory. +-- return taken amount and item name +function networks.liquid.take(pos, tlib2, outdir, name, amount, show_debug_cube) + assert(outdir) + assert(amount and amount > 0) + local taken = 0 + for _,item in ipairs(get_network_table(pos, tlib2, outdir, "tank")) do + local liq = LQD(item.pos) + if liq and liq.take then + if show_debug_cube then + networks.set_marker(item.pos, "take", 1.1, 1) + end + taken, name = liq.take(item.pos, item.indir, name, amount) + if taken and name and taken > 0 then + break + end + end + end + return taken, name +end + +function networks.liquid.untake(pos, tlib2, outdir, name, amount) + assert(outdir) + assert(name) + assert(amount and amount > 0) + for _,item in ipairs(get_network_table(pos, tlib2, outdir, "tank")) do + local liq = LQD(item.pos) + if liq and liq.untake then + amount = liq.untake(item.pos, item.indir, name, amount) + if not amount or amount == 0 then break end + end + end + return amount or 0 +end + +------------------------------------------------------------------------------- +-- Server/tank local functions +------------------------------------------------------------------------------- +function networks.liquid.is_empty(nvm) + return not nvm.liquid or (nvm.liquid.amount or 0) <= 0 +end + +function networks.liquid.get_amount(nvm) + if nvm.liquid and nvm.liquid.amount then + return nvm.liquid.amount + end + return 0 +end + +function networks.liquid.get_item(nvm) + local itemname = "" + if nvm.liquid and nvm.liquid.amount and nvm.liquid.amount > 0 and nvm.liquid.name then + itemname = nvm.liquid.name.." "..nvm.liquid.amount + end + return itemname +end + +function networks.liquid.srv_peek(nvm) + nvm.liquid = nvm.liquid or {} + return nvm.liquid.name +end + +function networks.liquid.srv_put(nvm, name, amount, capa) + assert(name) + assert(amount and amount > 0) + assert(capa and capa > 0) + + nvm.liquid = nvm.liquid or {} + amount = amount or 0 + if not nvm.liquid.name then + nvm.liquid.name = name + nvm.liquid.amount = amount + return 0 + elseif nvm.liquid.name == name then + nvm.liquid.amount = nvm.liquid.amount or 0 + if nvm.liquid.amount + amount <= capa then + nvm.liquid.amount = nvm.liquid.amount + amount + return 0 + else + local rest = nvm.liquid.amount + amount - capa + nvm.liquid.amount = capa + return rest + end + end + return amount +end + +function networks.liquid.srv_take(nvm, name, amount) + assert(amount and amount > 0) + + nvm.liquid = nvm.liquid or {} + amount = amount or 0 + if not name or nvm.liquid.name == name then + name = nvm.liquid.name + nvm.liquid.amount = nvm.liquid.amount or 0 + if nvm.liquid.amount > amount then + nvm.liquid.amount = nvm.liquid.amount - amount + return amount, name + else + local rest = nvm.liquid.amount + local name = nvm.liquid.name + nvm.liquid.amount = 0 + nvm.liquid.name = nil + return rest, name + end + end + return 0 +end + +------------------------------------------------------------------------------- +-- Valve +------------------------------------------------------------------------------- +function networks.liquid.turn_valve_on(pos, tlib2, name_off, name_on) + local node = N(pos) + local meta = M(pos) + if node.name == name_off then + node.name = name_on + minetest.swap_node(pos, node) + tlib2:after_place_tube(pos) + meta:set_int("networks_param2", node.param2) + return true + elseif meta:contains("networks_param2_copy") then + meta:set_int("networks_param2", meta:get_int("networks_param2_copy")) + tlib2:after_place_tube(pos) + return true + end +end + +function networks.liquid.turn_valve_off(pos, tlib2, name_off, name_on) + local node = N(pos) + local meta = M(pos) + if node.name == name_on then + node.name = name_off + minetest.swap_node(pos, node) + meta:set_int("networks_param2", 0) + tlib2:after_dig_tube(pos, node) + return true + elseif meta:contains("networks_param2") then + meta:set_int("networks_param2_copy", meta:get_int("networks_param2")) + meta:set_int("networks_param2", 0) + tlib2:after_dig_tube(pos, node) + return true + end +end diff --git a/networks.lua b/networks.lua index 0fe1043..e6f2e33 100644 --- a/networks.lua +++ b/networks.lua @@ -27,6 +27,7 @@ local NumNodes = 0 -- Used to determine the number of network nodes local Flip = tubelib2.Turn180Deg local get_nodename = networks.get_nodename local get_node = networks.get_node + ------------------------------------------------------------------------------- -- Debugging ------------------------------------------------------------------------------- @@ -57,6 +58,41 @@ local function network_nodes(netID, network) return "Network " .. netw_num(netID) .. ": " .. table.concat(tbl, ", ") end +-- Marker entities for debugging purposes +function networks.set_marker(pos, text, size, ttl) + local marker = minetest.add_entity(pos, "networks:marker_cube") + if marker ~= nil then + marker:set_nametag_attributes({color = "#FFFFFF", text = text}) + size = size or 1 + marker:set_properties({visual_size = {x = size, y = size}}) + if ttl then + minetest.after(ttl, marker.remove, marker) + end + end +end + +minetest.register_entity("networks:marker_cube", { + initial_properties = { + visual = "cube", + textures = { + "networks_marker.png", + "networks_marker.png", + "networks_marker.png", + "networks_marker.png", + "networks_marker.png", + "networks_marker.png", + }, + physical = false, + visual_size = {x = 1.1, y = 1.1}, + collisionbox = {-0.55,-0.55,-0.55, 0.55,0.55,0.55}, + glow = 8, + static_save = false, + }, + on_punch = function(self) + self.object:remove() + end, +}) + ------------------------------------------------------------------------------- -- Helper ------------------------------------------------------------------------------- @@ -66,6 +102,7 @@ local function net_def(pos, netw_type) if ndef and ndef.networks then return ndef.networks[netw_type] end + error("Node " .. get_nodename(pos) .. " at ".. P2S(pos) .. " has no 'ndef.networks'") end local function net_def2(pos, node_name, netw_type) @@ -450,5 +487,7 @@ end function networks.get_network_table(pos, tlib2, outdir) assert(outdir) local netID = get_netID(pos, outdir) - return get_network(tlib2.tube_type, netID) + if netID then + return get_network(tlib2.tube_type, netID) + end end diff --git a/power.lua b/power.lua index 278412d..620f90b 100644 --- a/power.lua +++ b/power.lua @@ -7,6 +7,8 @@ AGPL v3 See LICENSE.txt for more information + + Power API for power consuming and generating nodes ]]-- diff --git a/test/test_liquid.lua b/test/test_liquid.lua new file mode 100644 index 0000000..3a298e0 --- /dev/null +++ b/test/test_liquid.lua @@ -0,0 +1,430 @@ +--[[ + + Networks + ======== + + Copyright (C) 2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + +]]-- + +-- for lazy programmers +local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end +local S2P = minetest.string_to_pos +local M = minetest.get_meta + +local CYCLE_TIME = 2 +local STORAGE_CAPA = 500 +local AMOUNT = 2 + +local liquid = networks.liquid + +------------------------------------------------------------------------------- +-- Pipe +------------------------------------------------------------------------------- +local Pipe = tubelib2.Tube:new({ + dirs_to_check = {1,2,3,4,5,6}, + max_tube_length = 100, + tube_type = "liq", + primary_node_names = {"networks:pipeS", "networks:pipeA", "networks:valve_on"}, + secondary_node_names = {}, -- Will be added via 'liquids.register_nodes' + after_place_tube = function(pos, param2, tube_type, num_tubes, tbl) + if networks.node_to_be_replaced(pos, param2, tube_type, num_tubes) then + local name = minetest.get_node(pos).name + if name == "networks:valve_on" then + minetest.swap_node(pos, {name = "networks:valve_on", param2 = param2}) + elseif name == "networks:valve_off" then + minetest.swap_node(pos, {name = "networks:valve_off", param2 = param2}) + else + minetest.swap_node(pos, {name = "networks:pipe"..tube_type, param2 = param2}) + end + end + end, +}) + +-- Use global callback instead of node related functions +Pipe:register_on_tube_update2(function(pos, outdir, tlib2, node) + liquid.update_network(pos, outdir, tlib2, node) +end) + +minetest.register_node("networks:pipeS", { + description = "Pipe", + tiles = { -- Top, base, right, left, front, back + "networks_cable.png^[colorize:#007577:60", + "networks_cable.png^[colorize:#007577:60", + "networks_cable.png^[colorize:#007577:60", + "networks_cable.png^[colorize:#007577:60", + "networks_hole.png", + "networks_hole.png", + }, + after_place_node = function(pos, placer, itemstack, pointed_thing) + if not Pipe:after_place_tube(pos, placer, pointed_thing) then + minetest.remove_node(pos) + return true + end + return false + end, + after_dig_node = function(pos, oldnode, oldmetadata, digger) + Pipe:after_dig_tube(pos, oldnode, oldmetadata) + end, + paramtype2 = "facedir", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-3/16, -3/16, -4/8, 3/16, 3/16, 4/8}, + }, + }, + on_rotate = screwdriver.disallow, + paramtype = "light", + use_texture_alpha = "clip", + sunlight_propagates = true, + is_ground_content = false, + groups = {crumbly = 2, cracky = 2, snappy = 2}, + sounds = default.node_sound_defaults(), +}) + +minetest.register_node("networks:pipeA", { + description = "Pipe", + tiles = { -- Top, base, right, left, front, back + "networks_cable.png^[colorize:#007577:60", + "networks_hole.png^[colorize:#007577:60", + "networks_cable.png^[colorize:#007577:60", + "networks_cable.png^[colorize:#007577:60", + "networks_cable.png^[colorize:#007577:60", + "networks_hole.png^[colorize:#007577:60", + }, + after_dig_node = function(pos, oldnode, oldmetadata, digger) + Pipe:after_dig_tube(pos, oldnode, oldmetadata) + end, + paramtype2 = "facedir", + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-3/16, -4/8, -3/16, 3/16, 3/16, 3/16}, + {-3/16, -3/16, -4/8, 3/16, 3/16, -3/16}, + }, + }, + on_rotate = screwdriver.disallow, + paramtype = "light", + use_texture_alpha = "clip", + sunlight_propagates = true, + is_ground_content = false, + groups = {crumbly = 2, cracky = 2, snappy = 2, test_trowel = 1, not_in_creative_inventory=1}, + sounds = default.node_sound_defaults(), + drop = "networks:pipeS", +}) + +local size = 3/16 +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+ +} + +local names = networks.register_junction("networks:junction", size, Boxes, Pipe, { + description = "Junction", + tiles = {"networks_junction.png^[colorize:#007577:60"}, + after_place_node = function(pos, placer, itemstack, pointed_thing) + local name = "networks:junction" .. networks.junction_type(pos, Pipe) + minetest.swap_node(pos, {name = name, param2 = 0}) + Pipe:after_place_node(pos) + end, + -- junction needs own 'tubelib2_on_update2' to be able to call networks.junction_type + tubelib2_on_update2 = function(pos, outdir, tlib2, node) + local name = "networks:junction" .. networks.junction_type(pos, Pipe) + minetest.swap_node(pos, {name = name, param2 = 0}) + liquid.update_network(pos, 0, tlib2, node) + end, + after_dig_node = function(pos, oldnode, oldmetadata, digger) + Pipe:after_dig_node(pos) + end, + use_texture_alpha = "clip", + is_ground_content = false, + groups = {crumbly = 2, cracky = 2, snappy = 2}, + sounds = default.node_sound_defaults(), +}, 63) + +liquid.register_nodes(names, Pipe, "junc") + +------------------------------------------------------------------------------- +-- Pump +------------------------------------------------------------------------------- +local function swap_node(pos, name) + local node = tubelib2.get_node_lvm(pos) + if node.name == name then + return + end + node.name = name + minetest.swap_node(pos, node) +end + +local function turn_on(pos, mem) + swap_node(pos, "networks:pump_on") + M(pos):set_string("infotext", "pumping") + mem.running = true + -- enable marker cube + mem.dbg_cycles = 5 + minetest.get_node_timer(pos):start(CYCLE_TIME) +end + +local function turn_off(pos, mem) + swap_node(pos, "networks:pump_off") + M(pos):set_string("infotext", "off") + mem.running = false + minetest.get_node_timer(pos):stop() +end + +local function on_rightclick(pos, node, clicker) + local mem = tubelib2.get_mem(pos) + if not mem.running then + turn_on(pos, mem) + else + turn_off(pos, mem) + end +end + +local function pumping(pos) + local mem = tubelib2.get_mem(pos) + local outdir = M(pos):get_int("outdir") + local taken, name = liquid.take(pos, Pipe, networks.Flip[outdir], nil, AMOUNT, mem.dbg_cycles > 0) + print("pumping " .. name .. " " .. taken) + if taken > 0 then + local leftover = liquid.put(pos, Pipe, outdir, name, taken, mem.dbg_cycles > 0) + if leftover and leftover > 0 then + liquid.untake(pos, Pipe, networks.Flip[outdir], name, leftover) + if leftover == taken then + turn_off(pos, mem) + return false + end + end + end + mem.dbg_cycles = mem.dbg_cycles - 1 + return true +end + +local function after_place_node(pos) + local outdir = networks.side_to_outdir(pos, "B") + M(pos):set_int("outdir", outdir) + Pipe:after_place_node(pos, {outdir}) + M(pos):set_string("infotext", "off") + tubelib2.init_mem(pos) +end + +local function after_dig_node(pos, oldnode, oldmetadata) + local outdir = tonumber(oldmetadata.fields.outdir or 0) + Pipe:after_dig_node(pos, {outdir}) + tubelib2.del_mem(pos) +end + +minetest.register_node("networks:pump_off", { + description = "Pump", + tiles = { + -- up, down, right, left, back, front + 'networks_arrow.png^[colorize:#007577:60', + 'networks_pump.png^[colorize:#007577:60', + 'networks_pump.png^[colorize:#007577:60', + 'networks_pump.png^[colorize:#007577:60', + 'networks_conn.png^[colorize:#007577:60', + 'networks_conn.png^[colorize:#007577:60', + }, + after_place_node = after_place_node, + after_dig_node = after_dig_node, + on_timer = pumping, + on_rightclick = on_rightclick, + paramtype2 = "facedir", + on_rotate = screwdriver.disallow, + is_ground_content = false, + groups = {crumbly = 2, cracky = 2, snappy = 2}, + sounds = default.node_sound_defaults(), +}) + +minetest.register_node("networks:pump_on", { + description = "Pump", + tiles = { + -- up, down, right, left, back, front + 'networks_arrow.png^[colorize:#007577:60', + 'networks_pump.png^[colorize:#007577:60', + 'networks_pump.png^[colorize:#007577:60', + 'networks_pump.png^[colorize:#007577:60', + 'networks_conn.png^[colorize:#007577:60', + 'networks_conn.png^[colorize:#007577:60', + }, + after_place_node = after_place_node, + after_dig_node = after_dig_node, + on_timer = pumping, + on_rightclick = on_rightclick, + paramtype = "light", + light_source = 8, + paramtype2 = "facedir", + diggable = false, + drop = "", + groups = {not_in_creative_inventory = 1}, + is_ground_content = false, + sounds = default.node_sound_defaults(), +}) + +-- Pumps have to provide one output and one input side +liquid.register_nodes({"networks:pump_off", "networks:pump_on"}, Pipe, "pump", {"F", "B"}, {}) + +------------------------------------------------------------------------------- +-- Tank +------------------------------------------------------------------------------- +local function register_tank(name, description, liquid_name, liquid_amount) + minetest.register_node(name, { + description = description, + tiles = { + -- up, down, right, left, back, front + "networks_tank.png^[colorize:#007577:60", + "networks_tank.png^[colorize:#007577:60", + "networks_tank.png^[colorize:#007577:60", + "networks_tank.png^[colorize:#007577:60", + "networks_tank.png^[colorize:#007577:60", + 'networks_tank.png^[colorize:#007577:60', + }, + after_place_node = function(pos) + Pipe:after_place_node(pos) + local mem = tubelib2.init_mem(pos) + mem.liquid = {} + mem.liquid.name = liquid_name + mem.liquid.amount = liquid_amount + M(pos):set_string("infotext", networks.liquid.get_item(mem)) + minetest.get_node_timer(pos):start(CYCLE_TIME) + end, + after_dig_node = function(pos, oldnode, oldmetadata) + Pipe:after_dig_node(pos) + tubelib2.del_mem(pos) + end, + on_timer = function(pos, elapsed) + local mem = tubelib2.get_mem(pos) + M(pos):set_string("infotext", networks.liquid.get_item(mem)) + return true + end, + paramtype2 = "facedir", + on_rotate = screwdriver.disallow, + is_ground_content = false, + groups = {crumbly = 2, cracky = 2, snappy = 2}, + sounds = default.node_sound_defaults(), + }) +end + +-- 3 types of test tanks +register_tank("networks:tank1", "Water Tank", "water", STORAGE_CAPA) +register_tank("networks:tank2", "Milk Tank", "milk", STORAGE_CAPA) +register_tank("networks:tank3", "Empty Tank", nil, 0) + +liquid.register_nodes({"networks:tank1", "networks:tank2", "networks:tank3"}, + Pipe, "tank", nil, { + capa = STORAGE_CAPA, + peek = function(pos, indir) + local mem = tubelib2.get_mem(pos) + return liquid.srv_peek(mem) + end, + put = function(pos, indir, name, amount) + local mem = tubelib2.get_mem(pos) + return liquid.srv_put(mem, name, amount, STORAGE_CAPA) + end, + take = function(pos, indir, name, amount) + local mem = tubelib2.get_mem(pos) + return liquid.srv_take(mem, name, amount) + end, + untake = function(pos, indir, name, amount) + local mem = tubelib2.get_mem(pos) + return liquid.srv_put(mem, name, amount, STORAGE_CAPA) + end, + } +) + +------------------------------------------------------------------------------- +-- Valve +------------------------------------------------------------------------------- +local node_box = { + type = "fixed", + fixed = { + {-5/16, -5/16, -4/8, 5/16, 5/16, 4/8}, + }, +} + +-- The on-valve is a "primary node" like pipes +minetest.register_node("networks:valve_on", { + description = "Valve", + paramtype = "light", + drawtype = "nodebox", + node_box = node_box, + tiles = { + "networks_switch_on.png^[transformR90^[colorize:#007577:60", + "networks_switch_on.png^[transformR90^[colorize:#007577:60", + "networks_switch_on.png^[colorize:#007577:60", + "networks_switch_on.png^[colorize:#007577:60", + "networks_switch_hole.png^[colorize:#007577:60", + "networks_switch_hole.png^[colorize:#007577:60", + }, + after_place_node = function(pos, placer, itemstack, pointed_thing) + if not Pipe:after_place_tube(pos, placer, pointed_thing) then + minetest.remove_node(pos) + return true + end + return false + end, + on_rightclick = function(pos, node, clicker) + if liquid.turn_valve_off(pos, Pipe, "networks:valve_off", "networks:valve_on") then + minetest.sound_play("doors_glass_door_open", { + pos = pos, + gain = 1, + max_hear_distance = 5}) + end + end, + after_dig_node = function(pos, oldnode, oldmetadata, digger) + Pipe:after_dig_tube(pos, oldnode, oldmetadata) + end, + paramtype2 = "facedir", + on_rotate = screwdriver.disallow, + use_texture_alpha = "clip", + sunlight_propagates = true, + is_ground_content = false, + groups = {crumbly = 2, cracky = 2, snappy = 2}, + sounds = default.node_sound_defaults(), +}) + +-- The off-valve is a "secondary node" without connection sides +minetest.register_node("networks:valve_off", { + description = "Valve", + paramtype = "light", + drawtype = "nodebox", + node_box = node_box, + tiles = { + "networks_switch_off.png^[transformR90^[colorize:#007577:60", + "networks_switch_off.png^[transformR90^[colorize:#007577:60", + "networks_switch_off.png^[colorize:#007577:60", + "networks_switch_off.png^[colorize:#007577:60", + "networks_switch_hole.png^[colorize:#007577:60", + "networks_switch_hole.png^[colorize:#007577:60", + }, + on_rightclick = function(pos, node, clicker) + if liquid.turn_valve_on(pos, Pipe, "networks:valve_off", "networks:valve_on") then + minetest.sound_play("doors_glass_door_open", { + pos = pos, + gain = 1, + max_hear_distance = 5}) + end + end, + after_dig_node = function(pos, oldnode, oldmetadata, digger) + Pipe:after_dig_node(pos) + end, + paramtype2 = "facedir", + on_rotate = screwdriver.disallow, + use_texture_alpha = "clip", + sunlight_propagates = true, + is_ground_content = false, + drop = "networks:valve_on", + groups = {crumbly = 2, cracky = 2, snappy = 2, test_trowel = 1, not_in_creative_inventory = 1}, + sounds = default.node_sound_defaults(), +}) + +liquid.register_nodes({"networks:valve_off"}, Pipe, "tank", {}, {}) diff --git a/test/test_power.lua b/test/test_power.lua index a524afd..e36e345 100644 --- a/test/test_power.lua +++ b/test/test_power.lua @@ -35,7 +35,7 @@ local Cable = tubelib2.Tube:new({ max_tube_length = 100, tube_type = "pwr", primary_node_names = {"networks:cableS", "networks:cableA", "networks:switch_on"}, - secondary_node_names = {}, -- Will be added via 'power.register_node' + secondary_node_names = {}, -- Will be added via 'power.register_nodes' after_place_tube = function(pos, param2, tube_type, num_tubes, tbl) if networks.node_to_be_replaced(pos, param2, tube_type, num_tubes) then local name = minetest.get_node(pos).name @@ -342,7 +342,7 @@ local function swap_node(pos, name) minetest.swap_node(pos, node) end -local function turn_on(pos, tlib2) +local function turn_on(pos) swap_node(pos, "networks:consumer_on") M(pos):set_string("infotext", "on") local mem = tubelib2.get_mem(pos) @@ -350,7 +350,7 @@ local function turn_on(pos, tlib2) minetest.get_node_timer(pos):start(CYCLE_TIME) end -local function turn_off(pos, tlib2) +local function turn_off(pos) swap_node(pos, "networks:consumer") M(pos):set_string("infotext", "off") local mem = tubelib2.get_mem(pos) @@ -361,9 +361,9 @@ end local function on_rightclick(pos, node, clicker) local mem = tubelib2.get_mem(pos) if not mem.running and power.power_available(pos, Cable) then - turn_on(pos, Cable) + turn_on(pos) else - turn_off(pos, Cable) + turn_off(pos) end end diff --git a/textures/networks_arrow.png b/textures/networks_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..d04f43c80ab721f0d7fee5d7a7b7fa798b34701c GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9t9y9Y|NsB@2S4ZqiYR%y zIEHXsPfkckSn;3TskD^Gw2Vizh=;XC!Az=YMPdR2LwG9R@@3lJHUd>Mc)I$ztaD0e F0sv%>9bW(d literal 0 HcmV?d00001 diff --git a/textures/networks_pump.png b/textures/networks_pump.png new file mode 100644 index 0000000000000000000000000000000000000000..ac440548b1ef0bfb84da47c0d7735058b5e6493d GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9t9y9Y|NsB@2S4ZqipY7o zIEHXsPfkckSn;3TNwkdT>URN-BY)c+1Wb8&7&dwftvs+&z!#{J!PC{xWt~$(6968h B9Wwv` literal 0 HcmV?d00001 diff --git a/textures/networks_tank.png b/textures/networks_tank.png new file mode 100644 index 0000000000000000000000000000000000000000..d1df0288750a068f3f5e9c5570888ccc1ff3381f GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;TYyi9t9y9Y|NsB@2S4Zqib#37 xIEHXsPfkckSn;3TiM5EQ^nZa;hZGwd!`WQn`(>9tO$DlA@O1TaS?83{1OTQ}9E1P> literal 0 HcmV?d00001