--[[ TechAge ======= Copyright (C) 2019-2022 Joachim Stolberg AGPL v3 See LICENSE.txt for more information For chests and tanks with hyperloop support ]]-- -- 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 -- Will be initialized when mods are loaded local Stations = nil local Tube = nil local HYPERLOOP = nil techage.hyperloop = {} --[[ tStations["(x,y,z)"] = { conn = {dir = "(200,0,20)", ...}, name = , -- chest/tank owner = "singleplayer", conn_name = , single = true/nil, } ]]-- minetest.register_on_mods_loaded(function() if minetest.global_exists("hyperloop") then Stations = hyperloop.Stations Tube = hyperloop.Tube HYPERLOOP = true Tube:add_secondary_node_names({"techage:ta5_hl_chest", "techage:ta5_hl_tank"}) end end) local function get_remote_pos(pos, rmt_name) local owner = M(pos):get_string("owner") for key,item in pairs(Stations:get_node_table(pos)) do if item.owner == owner and item.conn_name == rmt_name then return S2P(key) end end end local function get_free_server_list(pos, owner) if Stations and Stations.get_node_table then local tbl = {M(pos):get_string("remote_name")} for key,item in pairs(Stations:get_node_table(pos) or {}) do if item.single and item.owner == owner then if M(pos):get_string("node_type") == M(S2P(key)):get_string("node_type") then tbl[#tbl+1] = item.conn_name end end end tbl[#tbl+1] = "" return tbl end return {} 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) if pos then local owner = M(pos):get_string("owner") return table.concat(get_free_server_list(pos, owner), ",") or "" end return "" end local function update_node_data(pos, state, conn_name, remote_name, rmt_pos) local meta = M(pos) local nvm = techage.get_nvm(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", "") meta:set_string("conn_status", S("connected to") .. " " .. 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) meta:set_string("conn_status", S("connected to") .. " " .. 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", "") 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", "") meta:set_string("conn_status", S("not connected")) nvm.rmt_pos = nil on_lose_connection(pos, "client") end end techage.hyperloop.SUBMENU = { { type = "label", label = S("Enter a block name or select an existing one"), tooltip = "", name = "l1", }, { type = "ascii", name = "conn_name", label = S("Block name"), tooltip = S("Connection name for this block"), default = "", }, { type = "dropdown", choices = "", on_dropdown = on_dropdown, name = "remote_name", label = S("Remote name"), tooltip = S("Connection name of the remote block"), }, } 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):get_string("status") == "client" then return true end end end 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):get_string("status") ~= "not connected" then return true end end end end function techage.hyperloop.remote_pos(pos) if HYPERLOOP then local nvm = techage.get_nvm(pos) if Stations:get(nvm.rmt_pos) then if M(pos):contains("remote_name") then return nvm.rmt_pos or pos end end end return pos end function techage.hyperloop.after_place_node(pos, placer, node_type) if HYPERLOOP then Stations:set(pos, node_type, {owner=placer:get_player_name()}) M(pos):set_string("node_type", node_type) Tube:after_place_node(pos) end end function techage.hyperloop.after_dig_node(pos, oldnode, oldmetadata, digger) if HYPERLOOP then local conn_name = oldmetadata.fields.conn_name local remote_name = oldmetadata.fields.remote_name local loc_pos, rmt_pos = pos, techage.get_nvm(pos).rmt_pos -- Close connections 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 update_node_data(rmt_pos, "client_not_connected", "", conn_name) end Tube:after_dig_node(pos) Stations:delete(pos) end end function techage.hyperloop.after_formspec(pos, fields) if HYPERLOOP and fields.save or fields.key_enter_field 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 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 end end end