Add ta5 chest for hyperloop transfer

This commit is contained in:
Joachim Stolberg 2021-12-30 15:05:20 +01:00
parent 33cf08f136
commit 8f037a4ec0
9 changed files with 408 additions and 79 deletions

View File

@ -49,6 +49,7 @@ end
local function after_dig_node(pos, oldnode, oldmetadata, digger)
techage.remove_node(pos, oldnode, oldmetadata)
techage.del_mem(pos)
end
local function formspec2()
@ -199,19 +200,7 @@ local function formspec4(pos)
"listring[current_player;main]"
end
local function formspec4_client(pos)
local location = "nodemeta:" .. pos.x .. "," .. pos.y .. "," .. pos.z
return "size[10,9]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"list[" .. location .. ";main;0,0;10,5;]"..
"list[current_player;main;1,5.3;8,4;]"..
"listring[" .. location .. ";main]"..
"listring[current_player;main]"
end
local function formspec4_server(pos)
local function formspec5(pos)
return "size[10,9]"..
default.gui_bg..
default.gui_bg_img..
@ -254,6 +243,10 @@ local function ta4_allow_metadata_inventory_put(pos, listname, index, stack, pla
return 0
end
if techage.hyperloop.is_client(pos) then
return 0
end
if listname == "main" then
return stack:get_count()
else
@ -267,6 +260,10 @@ local function ta4_allow_metadata_inventory_take(pos, listname, index, stack, pl
return 0
end
if techage.hyperloop.is_client(pos) then
return 0
end
if listname == "main" then
return stack:get_count()
else
@ -280,6 +277,10 @@ local function ta4_allow_metadata_inventory_move(pos, from_list, from_index, to_
return 0
end
if techage.hyperloop.is_client(pos) then
return 0
end
if from_list == "main" then
return count
else
@ -353,11 +354,10 @@ minetest.register_node("techage:chest_ta4", {
end,
on_rightclick = function(pos, node, clicker)
print("on_rightclick")
if hyperloop.is_client(pos) then
M(pos):set_string("formspec", formspec4_client(remote_pos(pos)))
M(pos):set_string("formspec", formspec5(pos))
elseif hyperloop.is_server(pos) then
M(pos):set_string("formspec", formspec4_server(pos))
M(pos):set_string("formspec", formspec5(pos))
end
end,
@ -365,6 +365,7 @@ minetest.register_node("techage:chest_ta4", {
after_dig_node = function(pos, oldnode, oldmetadata, digger)
techage.remove_node(pos, oldnode, oldmetadata)
hyperloop.after_dig_node(pos, oldnode, oldmetadata, digger)
techage.del_mem(pos)
end,
ta5_formspec = {menu=hyperloop.WRENCH_MENU, ex_points=EX_POINTS},
ta_after_formspec = hyperloop.after_formspec,

View File

@ -0,0 +1,232 @@
--[[
TechAge
=======
Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
TA5 Hyperloop Chest/Tank
]]--
-- for lazy programmers
local S2P = minetest.string_to_pos
local P2S = minetest.pos_to_string
local M = minetest.get_meta
local N = techage.get_node_lvm
local S = techage.S
local TA4_INV_SIZE = 32
local EX_POINTS = 20
local hyperloop = techage.hyperloop
local remote_pos = techage.hyperloop.remote_pos
local shared_inv = techage.shared_inv
local menu = techage.menu
local function can_dig(pos, player)
if minetest.is_protected(pos, player:get_player_name()) then
return false
end
shared_inv.before_inv_access(pos, "main")
local inv = minetest.get_meta(pos):get_inventory()
return inv:is_empty("main")
end
local function after_dig_node(pos, oldnode, oldmetadata, digger)
techage.remove_node(pos, oldnode, oldmetadata)
end
local function formspec(pos)
local ndef = minetest.registered_nodes["techage:ta5_hl_chest"]
local status = M(pos):get_string("conn_status")
if hyperloop.is_client(pos) or hyperloop.is_server(pos) then
local title = ndef.description .. " " .. status
return "size[8,9]"..
"box[0,-0.1;7.8,0.5;#c6e8ff]" ..
"label[0.2,-0.1;" .. minetest.colorize( "#000000", title) .. "]" ..
"list[context;main;0,1;8,4;]"..
"list[current_player;main;0,5.3;8,4;]"..
"listring[context;main]"..
"listring[current_player;main]"
else
return menu.generate_formspec(pos, ndef, hyperloop.SUBMENU)
end
end
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
shared_inv.before_inv_access(pos, listname)
local inv = minetest.get_inventory({type="node", pos=pos})
if inv:room_for_item(listname, stack) then
return stack:get_count()
end
return 0
end
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
shared_inv.before_inv_access(pos, listname)
local inv = minetest.get_inventory({type="node", pos=pos})
if inv:contains_item(listname, stack) then
return stack:get_count()
end
return 0
end
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
if shared_inv.before_inv_access(pos, "main") then
return 0
end
return count
end
minetest.register_node("techage:ta5_hl_chest", {
description = S("TA5 Hyperloop Chest"),
tiles = {
-- up, down, right, left, back, front
"techage_filling_ta4.png^techage_frame_ta5_top.png",
"techage_filling_ta4.png^techage_frame_ta5.png",
"techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_back_ta4.png",
"techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_back_ta4.png",
"techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_back_ta4.png",
"techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_chest_front_ta4.png",
},
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size('main', 32)
local number = techage.add_node(pos, "techage:ta5_hl_chest")
meta:set_string("node_number", number)
meta:set_string("owner", placer:get_player_name())
meta:set_string("formspec", formspec(pos))
meta:set_string("infotext", S("TA5 Hyperloop Chest").." "..number)
hyperloop.after_place_node(pos, placer, "chest")
end,
on_receive_fields = function(pos, formname, fields, player)
if minetest.is_protected(pos, player:get_player_name()) then
return
end
if techage.get_expoints(player) >= EX_POINTS then
if techage.menu.eval_input(pos, hyperloop.SUBMENU, fields) then
hyperloop.after_formspec(pos, fields)
M(pos):set_string("formspec", formspec(pos))
end
end
end,
on_timer = shared_inv.node_timer,
on_rightclick = function(pos, node, clicker)
shared_inv.on_rightclick(pos, node, clicker)
M(pos):set_string("formspec", formspec(pos))
end,
can_dig = can_dig,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
techage.remove_node(pos, oldnode, oldmetadata)
hyperloop.after_dig_node(pos, oldnode, oldmetadata, digger)
techage.del_mem(pos)
end,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_take = allow_metadata_inventory_take,
allow_metadata_inventory_move = allow_metadata_inventory_move,
on_metadata_inventory_put = shared_inv.after_inv_access,
on_metadata_inventory_take = shared_inv.after_inv_access,
paramtype2 = "facedir",
groups = {choppy=2, cracky=2, crumbly=2},
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
techage.register_node({"techage:ta5_hl_chest"}, {
on_inv_request = function(pos, in_dir, access_type)
pos = remote_pos(pos)
local meta = minetest.get_meta(pos)
return meta:get_inventory(), "main"
end,
on_pull_item = function(pos, in_dir, num, item_name)
pos = remote_pos(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local mem = techage.get_mem(pos)
mem.filter = mem.filter or mConf.item_filter(pos, TA4_INV_SIZE)
mem.chest_configured = mem.chest_configured or not inv:is_empty("conf")
if inv:is_empty("main") then
return nil
end
if item_name then
if mem.filter[item_name] or not mem.chest_configured then
local taken = inv:remove_item("main", {name = item_name, count = num})
if taken:get_count() > 0 then
return taken
end
end
else -- no item given
if mem.chest_configured then
return mConf.take_item(pos, inv, "main", num, mem.filter["unconfigured"])
else
return techage.get_items(pos, inv, "main", num)
end
end
end,
on_push_item = function(pos, in_dir, item, idx)
pos = remote_pos(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local mem = techage.get_mem(pos)
mem.filter = mem.filter or mConf.item_filter(pos, TA4_INV_SIZE)
mem.chest_configured = mem.chest_configured or not inv:is_empty("conf")
if mem.chest_configured then
local name = item:get_name()
local stacks = mem.filter[name] or mem.filter["unconfigured"]
return mConf.put_items(pos, inv, "main", item, stacks, idx)
else
return techage.put_items(inv, "main", item, idx)
end
end,
on_unpull_item = function(pos, in_dir, item)
pos = remote_pos(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local mem = techage.get_mem(pos)
mem.filter = mem.filter or mConf.item_filter(pos, TA4_INV_SIZE)
mem.chest_configured = mem.chest_configured or not inv:is_empty("conf")
if mem.chest_configured then
local name = item:get_name()
local stacks = mem.filter[name] or mem.filter["unconfigured"]
return mConf.put_items(pos, inv, "main", item, stacks)
else
return techage.put_items(inv, "main", item)
end
end,
on_recv_message = function(pos, src, topic, payload)
if topic == "state" then
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return techage.get_inv_state(inv, "main")
else
return "unsupported"
end
end,
})
minetest.register_craft({
type = "shapeless",
output = "techage:ta5_hl_chest",
recipe = {"techage:chest_ta4", "techage:aichip"}
})

View File

@ -262,6 +262,28 @@ function techage.repair_number(pos)
end
end
-- Like techage.add_node, but use the old number again
function techage.unpack_node(pos, name, number)
if item_handling_node(name) then
Tube:after_place_node(pos)
end
local key = minetest.hash_node_position(pos)
NumbersToBeRecycled[key] = nil
if number then
backend.set_nodepos(number, pos)
end
end
-- Like techage.remove_node but don't store the number for this position
function techage.pack_node(pos, oldnode, number)
if number then
NodeInfoCache[number] = nil
end
if oldnode and item_handling_node(oldnode.name) then
Tube:after_dig_node(pos)
end
end
-------------------------------------------------------------------
-- Node register function

View File

@ -43,10 +43,7 @@ minetest.register_on_mods_loaded(function()
Stations = hyperloop.Stations
Tube = hyperloop.Tube
HYPERLOOP = true
Tube:add_secondary_node_names({"techage:ta4_tank", "techage:chest_ta4"})
else
techage.hyperloop.WRENCH_MENU[2] = nil
techage.hyperloop.WRENCH_MENU[1] = nil
Tube:add_secondary_node_names({"techage:ta5_hl_chest", "techage:ta5_hl_tank"})
end
end)
@ -72,6 +69,14 @@ local function get_free_server_list(pos, owner)
return tbl
end
local function on_lose_connection(pos, node_type)
local name = techage.get_node_lvm(pos).name
local ndef = minetest.registered_nodes[name]
if ndef and ndef.on_lose_connection then
ndef.on_lose_connection(pos, node_type)
end
end
local function on_dropdown(pos)
local owner = M(pos):get_string("owner")
return table.concat(get_free_server_list(pos, owner), ",")
@ -83,32 +88,38 @@ local function update_node_data(pos, state, conn_name, remote_name, rmt_pos)
if state == "server_connected" then
Stations:update(pos, {conn_name=conn_name, single="nil"})
meta:set_string("status", "server")
meta:set_string("conn_name", conn_name)
meta:set_string("remote_name", "")
nvm.conn_status = P2S(rmt_pos)
meta:set_string("conn_status", S("connected with") .. " " .. P2S(rmt_pos))
nvm.rmt_pos = rmt_pos
elseif state == "client_connected" then
Stations:update(pos, {conn_name="nil", single="nil"})
meta:set_string("status", "client")
meta:set_string("conn_name", "")
meta:set_string("remote_name", remote_name)
nvm.conn_status = P2S(rmt_pos)
meta:set_string("conn_status", S("connected with") .. " " .. P2S(rmt_pos))
nvm.rmt_pos = rmt_pos
elseif state == "server_not_connected" then
Stations:update(pos, {conn_name=conn_name, single=true})
meta:set_string("status", "server")
meta:set_string("conn_name", conn_name)
meta:set_string("remote_name", "")
nvm.conn_status = S("not connected")
meta:set_string("conn_status", S("not connected"))
nvm.rmt_pos = nil
on_lose_connection(pos, "server")
elseif state == "client_not_connected" then
Stations:update(pos, {conn_name="nil", single=nil})
meta:set_string("status", "not connected")
meta:set_string("conn_name", "")
meta:set_string("remote_name", "")
nvm.conn_status = S("not connected")
meta:set_string("conn_status", S("not connected"))
nvm.rmt_pos = nil
on_lose_connection(pos, "client")
end
end
techage.hyperloop.WRENCH_MENU = {
techage.hyperloop.SUBMENU = {
{
type = "label",
label = S("Enter a block name or select an existing one"),
@ -130,20 +141,14 @@ techage.hyperloop.WRENCH_MENU = {
label = S("Remote name"),
tooltip = S("Connection name of the remote block"),
},
{
type = "output",
name = "conn_status",
label = S("Connected to"),
tooltip = S("Connection status"),
default = S("not connected"),
},
}
function techage.hyperloop.is_client(pos)
if HYPERLOOP then
local nvm = techage.get_nvm(pos)
if Stations:get(nvm.rmt_pos) then
if M(pos):contains("remote_name") then
if M(pos):get_string("status") == "client" then
print("is_client2", true)
return true
end
end
@ -151,10 +156,18 @@ function techage.hyperloop.is_client(pos)
end
function techage.hyperloop.is_server(pos)
if HYPERLOOP then
if M(pos):get_string("status") == "server" then
return true
end
end
end
function techage.hyperloop.is_paired(pos)
if HYPERLOOP then
local nvm = techage.get_nvm(pos)
if Stations:get(nvm.rmt_pos) then
if M(pos):contains("conn_name") then
if M(pos):get_string("status") ~= "not connected" then
return true
end
end
@ -188,9 +201,9 @@ function techage.hyperloop.after_dig_node(pos, oldnode, oldmetadata, digger)
local loc_pos, rmt_pos = pos, techage.get_nvm(pos).rmt_pos
-- Close connections
if remote_name ~= "" and rmt_pos then -- Connected client
if remote_name and rmt_pos then -- Connected client
update_node_data(rmt_pos, "server_not_connected", remote_name, "")
elseif conn_name ~= "" and rmt_pos then -- Connected server
elseif conn_name and rmt_pos then -- Connected server
update_node_data(rmt_pos, "client_not_connected", "", conn_name)
end
@ -199,34 +212,24 @@ function techage.hyperloop.after_dig_node(pos, oldnode, oldmetadata, digger)
end
end
function techage.hyperloop.after_formspec(pos, fields, playername)
function techage.hyperloop.after_formspec(pos, fields)
if HYPERLOOP and fields.save then
local meta = M(pos)
local conn_name = meta:get_string("conn_name")
local remote_name = meta:get_string("remote_name")
local status = meta:contains("status") and meta:get_string("status") or "not connected"
local loc_pos, rmt_pos = pos, techage.get_nvm(pos).rmt_pos
-- Close connections
if remote_name ~= "" then -- Connected client
update_node_data(loc_pos, "client_not_connected", "", remote_name)
if rmt_pos then
update_node_data(rmt_pos, "server_not_connected", remote_name, "")
if status == "not connected" then
if fields.remote_name ~= "" then -- Client
local rmt_pos = get_remote_pos(pos, fields.remote_name)
if rmt_pos then
update_node_data(loc_pos, "client_connected", "", fields.remote_name, rmt_pos)
update_node_data(rmt_pos, "server_connected", fields.remote_name, "", loc_pos)
end
elseif fields.conn_name ~= "" then -- Server
update_node_data(loc_pos, "server_not_connected", fields.conn_name, "")
end
elseif conn_name ~= "" and conn_name ~= fields.conn_name then -- Connected server
update_node_data(loc_pos, "server_not_connected", conn_name, "")
if rmt_pos then
update_node_data(rmt_pos, "client_not_connected", "", conn_name)
end
end
if fields.remote_name ~= "" then -- Client
local rmt_pos = get_remote_pos(pos, fields.remote_name)
if rmt_pos then
update_node_data(loc_pos, "client_connected", "", fields.remote_name, rmt_pos)
update_node_data(rmt_pos, "server_connected", fields.remote_name, "", loc_pos)
end
elseif fields.conn_name ~= "" then -- Server
update_node_data(loc_pos, "server_not_connected", fields.conn_name, "")
end
end
end

69
basis/shared_inv.lua Normal file
View File

@ -0,0 +1,69 @@
--[[
TechAge
=======
Copyright (C) 2019-2021 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
Library for shared inventories
]]--
-- for lazy programmers
local S2P = minetest.string_to_pos
local P2S = minetest.pos_to_string
local M = minetest.get_meta
local S = techage.S
techage.shared_inv = {}
local hyperloop = techage.hyperloop
local remote_pos = techage.hyperloop.remote_pos
local function copy_inventory_list(from_pos, to_pos, listname)
local inv1 = minetest.get_inventory({type="node", pos=from_pos})
local inv2 = minetest.get_inventory({type="node", pos=to_pos})
inv2:set_list(listname, inv1:get_list(listname))
end
function techage.shared_inv.node_timer(pos, elapsed)
local rmt_pos = remote_pos(pos)
if techage.is_activeformspec(pos) then
copy_inventory_list(rmt_pos, pos, "main")
return true
end
return false
end
-- Synchronize the client inventory with the server one
function techage.shared_inv.before_inv_access(pos, listname)
print("before_inv_access", listname)
if hyperloop.is_client(pos) then
local rmt_pos = remote_pos(pos)
copy_inventory_list(rmt_pos, pos, listname)
return true
end
return false
end
-- Synchronize the client inventory with the server one
function techage.shared_inv.after_inv_access(pos, listname)
print("after_inv_access", listname)
if hyperloop.is_client(pos) then
local rmt_pos = remote_pos(pos)
copy_inventory_list(pos, rmt_pos, listname)
return true
end
return false
end
function techage.shared_inv.on_rightclick(pos, node, clicker)
if hyperloop.is_client(pos) then
copy_inventory_list(remote_pos(pos), pos, "main")
techage.set_activeformspec(pos, clicker)
end
end

View File

@ -3,7 +3,7 @@
TechAge
=======
Copyright (C) 2019-2021 Joachim Stolberg
Copyright (C) 2019-2022 Joachim Stolberg
AGPL v3
See LICENSE.txt for more information
@ -13,7 +13,7 @@
local S = techage.S
local menu = {}
techage.menu = {}
local function index(list, x)
for idx, v in ipairs(list) do
@ -93,7 +93,7 @@ local function generate_formspec_substring(pos, meta, form_def, player_name)
elseif elem.type == "const" then
tbl[#tbl+1] = "label[4.75," .. offs .. ";" .. elem.value .. "]"
elseif elem.type == "output" then
local val = nvm[elem.name] or ""
local val = nvm[elem.name] or meta:get_string(elem.name) or ""
if tonumber(val) then
val = techage.round(val)
end
@ -114,6 +114,7 @@ local function generate_formspec_substring(pos, meta, form_def, player_name)
local choices = elem.on_dropdown(pos)
local l = choices:split(",")
local idx = index(l, val) or 1
print("choices", dump(choices), idx, val)
tbl[#tbl+1] = "dropdown[4.72," .. (offs) .. ";5.5,1.4;" .. elem.name .. ";" .. choices .. ";" .. idx .. "]"
else
local val = elem.default
@ -204,7 +205,7 @@ local function evaluate_data(pos, meta, form_def, fields, player_name)
if fields[elem.name] ~= nil then
meta:set_string(elem.name, fields[elem.name])
end
elseif elem.type == "items" then
elseif elem.type == "items" and player_name then
local inv_name = minetest.formspec_escape(player_name) .. "_techage_wrench_menu"
local dinv = minetest.get_inventory({type = "detached", name = inv_name})
local ninv = minetest.get_inventory({type = "node", pos = pos})
@ -219,25 +220,26 @@ local function evaluate_data(pos, meta, form_def, fields, player_name)
return res
end
function menu.generate_formspec(pos, ndef, form_def, player_name)
function techage.menu.generate_formspec(pos, ndef, form_def, player_name)
local meta = minetest.get_meta(pos)
local number = techage.get_node_number(pos)
local mem = techage.get_mem(pos)
mem.star = ((mem.star or 0) + 1) % 2
local star = mem.star == 1 and "*" or ""
local inv_name = minetest.formspec_escape(player_name) .. "_techage_wrench_menu"
minetest.create_detached_inventory(inv_name, {
allow_put = allow_put,
allow_take = allow_take})
local dinv = minetest.get_inventory({type = "detached", name = inv_name})
local ninv = minetest.get_inventory({type = "node", pos = pos})
if dinv and ninv then
dinv:set_size('cfg', ninv:get_size("cfg"))
for i = 1, ninv:get_size("cfg") do
dinv:set_stack("cfg", i, ninv:get_stack("cfg", i))
if player_name then
local inv_name = minetest.formspec_escape(player_name) .. "_techage_wrench_menu"
minetest.create_detached_inventory(inv_name, {
allow_put = allow_put,
allow_take = allow_take})
local dinv = minetest.get_inventory({type = "detached", name = inv_name})
local ninv = minetest.get_inventory({type = "node", pos = pos})
if dinv and ninv then
dinv:set_size('cfg', ninv:get_size("cfg"))
for i = 1, ninv:get_size("cfg") do
dinv:set_stack("cfg", i, ninv:get_stack("cfg", i))
end
end
end
if meta and number and ndef and form_def then
local title = ndef.description .. " (" .. number .. ")"
local player_inv_needed, text = generate_formspec_substring(pos, meta, form_def, player_name)
@ -286,13 +288,10 @@ function menu.generate_formspec(pos, ndef, form_def, player_name)
return ""
end
function menu.eval_input(pos, form_def, fields, player_name)
--print(dump(fields))
function techage.menu.eval_input(pos, form_def, fields, player_name)
if fields.save then
local meta = minetest.get_meta(pos)
evaluate_data(pos, meta, form_def, fields, player_name)
end
return fields.refresh or fields.save
end
return menu

View File

@ -351,7 +351,7 @@ local function test_magnet(pos, payload)
if res then
techage.send_single(own_num, term_num, "text", "magnet #" .. magnet_num .. ": ok")
else
techage.send_single(own_num, term_num, "text", "magnet #" .. magnet_num .. ": " .. err .. "!!!")
techage.send_single(own_num, term_num, "text", "magnet #" .. magnet_num .. ": " .. (err or "unknown error") .. "!!!")
end
end

View File

@ -100,6 +100,8 @@ dofile(MP.."/basis/laser_lib.lua")
dofile(MP.."/basis/legacy.lua")
dofile(MP.."/basis/hyperloop.lua")
dofile(MP.."/basis/oggfiles.lua")
dofile(MP.."/basis/submenu.lua")
dofile(MP.."/basis/shared_inv.lua")
-- Main doc
dofile(MP.."/doc/manual_DE.lua")
@ -190,6 +192,7 @@ dofile(MP.."/basic_machines/itemsource.lua")
dofile(MP.."/basic_machines/recycler.lua")
dofile(MP.."/basic_machines/concentrator.lua")
dofile(MP.."/basic_machines/recipeblock.lua")
dofile(MP.."/basic_machines/ta5_chest.lua")
-- Liquids II
dofile(MP.."/liquids/tank.lua")

View File

@ -17,7 +17,7 @@ local S = techage.S
local Cable1 = techage.ElectricCable
local Cable2 = techage.TA4_Cable
local Pipe2 = techage.LiquidPipe
local menu = dofile(minetest.get_modpath("techage") .. "/tools/submenu.lua")
local menu = techage.menu
local function network_check(start_pos, Cable, player_name)
-- local ndef = techage.networks.net_def(start_pos, Cable.tube_type)