From 577a4e8bd3db05fd61c54f9485bd27f540af6180 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Sun, 2 Jan 2022 21:00:46 +0100 Subject: [PATCH] Add ta5 teleport tubes --- basic_machines/consumer.lua | 8 +- basis/hyperloop.lua | 6 +- basis/node_states.lua | 3 +- basis/submenu.lua | 4 +- basis/teleport.lua | 149 ++++++++++++++++++++++ init.lua | 3 + teleport/teleport_tube.lua | 227 +++++++++++++++++++++++++++++++++ textures/techage_appl_wifi.png | Bin 0 -> 163 bytes 8 files changed, 390 insertions(+), 10 deletions(-) create mode 100644 basis/teleport.lua create mode 100644 teleport/teleport_tube.lua create mode 100644 textures/techage_appl_wifi.png diff --git a/basic_machines/consumer.lua b/basic_machines/consumer.lua index d99a9ec..f745a59 100644 --- a/basic_machines/consumer.lua +++ b/basic_machines/consumer.lua @@ -3,14 +3,14 @@ TechAge ======= - Copyright (C) 2019-2020 Joachim Stolberg + Copyright (C) 2019-2022 Joachim Stolberg AGPL v3 See LICENSE.txt for more information Consumer node basis functionality. It handles: - - up to 3 stages of nodes (TA2/TA3/TA4) + - up to 4 stages of nodes (TA2/TA3/TA4/TA5) - power consumption - node state handling - registration of passive and active nodes @@ -119,7 +119,7 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState if not node_name_prefix then node_name_prefix = "techage:ta" end - for stage = 2,4 do + for stage = 2,5 do local name_pas = node_name_prefix..stage.."_"..base_name.."_pas" local name_act = node_name_prefix..stage.."_"..base_name.."_act" local name_inv = "TA"..stage.." "..inv_name @@ -299,5 +299,5 @@ function techage.register_consumer(base_name, inv_name, tiles, tNode, validState end end end - return names[1], names[2], names[3] + return names[1], names[2], names[3], names[4] end diff --git a/basis/hyperloop.lua b/basis/hyperloop.lua index bcae2bf..d5e1c64 100644 --- a/basis/hyperloop.lua +++ b/basis/hyperloop.lua @@ -91,14 +91,14 @@ local function update_node_data(pos, state, conn_name, remote_name, rmt_pos) meta:set_string("status", "server") meta:set_string("conn_name", conn_name) meta:set_string("remote_name", "") - meta:set_string("conn_status", S("connected with") .. " " .. P2S(rmt_pos)) + 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 with") .. " " .. P2S(rmt_pos)) + 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}) @@ -212,7 +212,7 @@ function techage.hyperloop.after_dig_node(pos, oldnode, oldmetadata, digger) end function techage.hyperloop.after_formspec(pos, fields) - if HYPERLOOP and fields.save then + 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") diff --git a/basis/node_states.lua b/basis/node_states.lua index 9e76c89..ea4a29d 100644 --- a/basis/node_states.lua +++ b/basis/node_states.lua @@ -174,6 +174,7 @@ function NodeStates:new(attr) cycle_time = attr.cycle_time, -- for running state standby_ticks = attr.standby_ticks, -- for standby state -- optional + countdown_ticks = attr.countdown_ticks or 1, node_name_passive = attr.node_name_passive, node_name_active = attr.node_name_active, infotext_name = attr.infotext_name, @@ -254,7 +255,7 @@ function NodeStates:start(pos, nvm) if self.start_node then self.start_node(pos, nvm, state) end - nvm.techage_countdown = 1 + nvm.techage_countdown = self.countdown_ticks if self.node_name_active then swap_node(pos, self.node_name_active) end diff --git a/basis/submenu.lua b/basis/submenu.lua index 9405927..f7011db 100644 --- a/basis/submenu.lua +++ b/basis/submenu.lua @@ -288,9 +288,9 @@ function techage.menu.generate_formspec(pos, ndef, form_def, player_name) end function techage.menu.eval_input(pos, form_def, fields, player_name) - if fields.save then + if fields.save or fields.key_enter_field then local meta = minetest.get_meta(pos) evaluate_data(pos, meta, form_def, fields, player_name) end - return fields.refresh or fields.save + return fields.refresh or fields.save or fields.key_enter_field end diff --git a/basis/teleport.lua b/basis/teleport.lua new file mode 100644 index 0000000..e92b7ef --- /dev/null +++ b/basis/teleport.lua @@ -0,0 +1,149 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2022 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + For tupe/pipe blocks with teleport support + +]]-- + +-- for lazy programmers +local S2P = minetest.string_to_pos +local P2S = minetest.pos_to_string +local NDEF = function(pos) return minetest.registered_nodes[techage.get_node_lvm(pos).name] or {} end +local M = minetest.get_meta +local S = techage.S +local menu = techage.menu + +techage.teleport = {} + +local PairingList = {} -- {owner = {node_type = {channel = pos}}} + +local function get_pairing_table1(meta) + local owner = meta:get_string("owner") + local node_type = meta:get_string("tele_node_type") + PairingList[owner] = PairingList[owner] or {} + PairingList[owner][node_type] = PairingList[owner][node_type] or {} + return PairingList[owner][node_type] +end + +local function get_pairing_table2(oldmetadata) + local owner = oldmetadata.fields.owner + local node_type = oldmetadata.fields.tele_node_type + PairingList[owner] = PairingList[owner] or {} + PairingList[owner][node_type] = PairingList[owner][node_type] or {} + return PairingList[owner][node_type] +end + +local function get_free_server_list(pos) + local tbl = {""} + for name, pos in pairs(get_pairing_table1(M(pos))) do + table.insert(tbl, name) + end + return table.concat(tbl, ",") +end + +local TELE_MENU = { + { + 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 = get_free_server_list, + name = "remote_name", + label = S("Remote name"), + tooltip = S("Connection name of the remote block"), + }, +} + +function techage.teleport.formspec(pos) + local ndef = NDEF(pos) + return menu.generate_formspec(pos, ndef, TELE_MENU) +end + +local function store_connection(pos, peer_pos) + local meta = M(pos) + local status = S("connected to") .. " " .. P2S(peer_pos) + meta:set_string("tele_status", status) + meta:set_string("tele_peer_pos", P2S(peer_pos)) + meta:set_string("formspec", "") +end + +function techage.teleport.prepare_pairing(pos, node_type, status) + local meta = M(pos) + if node_type then + meta:set_string("tele_node_type", node_type) + end + status = status or S("not connected") + meta:set_string("tele_status", status) + meta:set_string("tele_peer_pos", "") + meta:set_string("formspec", techage.teleport.formspec(pos)) +end + +function techage.teleport.stop_pairing(pos, oldmetadata) + -- disconnect peer node + if oldmetadata and oldmetadata.fields then + if oldmetadata.fields.tele_peer_pos then + local peer_pos = S2P(oldmetadata.fields.tele_peer_pos) + local meta = M(peer_pos) + if meta:get_string("conn_name") ~= "" then -- Server + local tbl = get_pairing_table1(meta) + tbl[meta:get_string("conn_name")] = peer_pos + techage.teleport.prepare_pairing(peer_pos, nil, S("server not connected")) + else + techage.teleport.prepare_pairing(peer_pos) + end + elseif oldmetadata.fields.conn_name then + local tbl = get_pairing_table2(oldmetadata) + tbl[oldmetadata.fields.conn_name] = nil + end + end +end + +function techage.teleport.is_connected(pos) + return M(pos):get_string("tele_peer_pos") ~= "" +end + +function techage.teleport.get_remote_pos(pos) + local s = M(pos):get_string("tele_peer_pos") + if s ~= "" then + return S2P(s) + end +end + +function techage.teleport.after_formspec(pos, fields) + if techage.menu.eval_input(pos, TELE_MENU, fields) then + if not techage.teleport.is_connected(pos) then + local meta = M(pos) + if fields.remote_name ~= "" then -- Client + local tbl = get_pairing_table1(meta) + local peer_pos = tbl[fields.remote_name] + if peer_pos then + tbl[fields.remote_name] = nil + store_connection(pos, peer_pos) + store_connection(peer_pos, pos) + end + elseif fields.conn_name ~= "" then -- Server + local tbl = get_pairing_table1(meta) + tbl[fields.conn_name] = pos + techage.teleport.prepare_pairing(pos, nil, S("server not connected")) + end + end + end +end diff --git a/init.lua b/init.lua index 18a491c..bffcbe1 100644 --- a/init.lua +++ b/init.lua @@ -103,6 +103,7 @@ dofile(MP.."/basis/oggfiles.lua") dofile(MP.."/basis/submenu.lua") dofile(MP.."/basis/shared_inv.lua") dofile(MP.."/basis/shared_tank.lua") +dofile(MP.."/basis/teleport.lua") -- Main doc dofile(MP.."/doc/manual_DE.lua") @@ -393,6 +394,8 @@ dofile(MP.."/collider/cooler.lua") dofile(MP.."/collider/detector.lua") dofile(MP.."/collider/worker.lua") +dofile(MP.."/teleport/teleport_tube.lua") + -- Prevent other mods from using IE techage.IE = nil diff --git a/teleport/teleport_tube.lua b/teleport/teleport_tube.lua new file mode 100644 index 0000000..c54d5c2 --- /dev/null +++ b/teleport/teleport_tube.lua @@ -0,0 +1,227 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2017-2022 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA5 teleport nodes + +]]-- + +-- 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 S = techage.S + +local Tube = techage.Tube +local teleport = techage.teleport +local Cable = techage.ElectricCable +--local Cable = techage.Axle +local power = networks.power + +local STANDBY_TICKS = 4 +local COUNTDOWN_TICKS = 4 +local CYCLE_TIME = 2 +local PWR_NEEDED = 12 +local EX_POINTS = 60 +local DESCRIPTION = S("TA5 Teleport Tube") + +-- 2 Blöcke on/off +-- Strom von 7 Seiten +-- Pipe/Tube nur von einer Seite +-- TA5 Design +-- Consumer block mit on/off +-- Inventory mit 4 stacks +-- wrench menü? +-- normales Menü wenn connected + +local WRENCH_MENU = { + { + type = "dropdown", + choices = "1,2,4,6,8,12,16", + name = "ontime", + label = S("On Time") .. " [s]", + tooltip = S("The time between the 'on' and 'off' commands."), + default = "1", + }, + { + type = "dropdown", + choices = "2,4,6,8,12,16,20", + name = "blockingtime", + label = S("Blocking Time") .. " [s]", + tooltip = S("The time after the 'off' command\nuntil the next 'on' command is accepted."), + default = "8", + }, + { + type = "items", + name = "config", + label = S("Configured Items"), + tooltip = S("Items which generate an 'on' command.\nIf empty, all passed items generate an 'on' command."), + size = 4, + } +} + +local function formspec(self, pos, nvm) + local title = DESCRIPTION .. " " .. M(pos):get_string("tele_status") + return "size[8,2]".. + "box[0,-0.1;7.8,0.5;#c6e8ff]" .. + "label[0.5,-0.1;" .. minetest.colorize( "#000000", title) .. "]" .. + "image_button[3.5,1;1,1;" .. self:get_state_button_image(nvm) .. ";state_button;]" .. + "tooltip[3.5,1;1,1;" .. self:get_state_tooltip(nvm) .. "]" +end + +local function can_start(pos, nvm, state) + return teleport.is_connected(pos) +end + +local State = techage.NodeStates:new({ + node_name_passive = "techage:ta5_tele_tube", + infotext_name = DESCRIPTION, + cycle_time = CYCLE_TIME, + standby_ticks = STANDBY_TICKS, + countdown_ticks = COUNTDOWN_TICKS, + formspec_func = formspec, + can_start = can_start, +}) + +local function consume_power(pos, nvm) + if techage.needs_power(nvm) then + local taken = power.consume_power(pos, Cable, nil, PWR_NEEDED) + if techage.is_running(nvm) then + if taken < PWR_NEEDED then + State:nopower(pos, nvm) + else + return true -- keep running + end + elseif taken == PWR_NEEDED then + State:start(pos, nvm) + end + end +end + +minetest.register_node("techage:ta5_tele_tube", { + description = DESCRIPTION, + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta4.png^techage_frame_ta5_top.png", + "techage_filling_ta4.png^techage_frame_ta5_top.png", + "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_wifi.png", + "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_hole_tube.png", + "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_wifi.png", + "techage_filling_ta4.png^techage_frame_ta5.png^techage_appl_wifi.png", + }, + + after_place_node = function(pos, placer) + local meta = M(pos) + local nvm = techage.get_nvm(pos) + local node = minetest.get_node(pos) + local tube_dir = techage.side_to_outdir("L", node.param2) + local number = techage.add_node(pos, "techage:ta5_tele_tube") + nvm.running = false + State:node_init(pos, nvm, number) + meta:set_int("tube_dir", tube_dir) + meta:set_string("owner", placer:get_player_name()) + Tube:after_place_node(pos, {tube_dir}) + Cable:after_place_node(pos) + teleport.prepare_pairing(pos, "ta5_tele_tube") + end, + + on_receive_fields = function(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + if teleport.is_connected(pos) then + local nvm = techage.get_nvm(pos) + State:state_button_event(pos, nvm, fields) + M(pos):set_string("formspec", formspec(State, pos, nvm)) + else + if techage.get_expoints(player) >= EX_POINTS then + teleport.after_formspec(pos, fields) + end + end + end, + + on_rightclick = function(pos, clicker, listname) + if teleport.is_connected(pos) then + local nvm = techage.get_nvm(pos) + M(pos):set_string("formspec", formspec(State, pos, nvm)) + else + M(pos):set_string("formspec", teleport.formspec(pos)) + end + end, + + on_timer = function(pos, elapsed) + local nvm = techage.get_nvm(pos) + consume_power(pos, nvm) + -- the state has to be triggered by on_push_item + State:idle(pos, nvm) + return State:is_active(nvm) + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + techage.remove_node(pos, oldnode, oldmetadata) + teleport.stop_pairing(pos, oldmetadata) + Tube:after_dig_node(pos) + Cable:after_dig_node(pos) + techage.del_mem(pos) + end, + + paramtype2 = "facedir", -- important! + on_rotate = screwdriver.disallow, -- important! + is_ground_content = false, + groups = {choppy=2, cracky=2, crumbly=2}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_craft({ + output = "techage:ta5_tele_tube", + recipe = { + {"", "dye:red", ""}, + {"techage:ta4_tubeS", "techage:ta5_aichip", ""}, + {"", "group:wood", ""}, + }, +}) + +techage.register_node({"techage:ta5_tele_tube"}, { + on_push_item = function(pos, in_dir, stack) + local nvm = techage.get_nvm(pos) + if techage.is_operational(nvm) then + local rmt_pos = teleport.get_remote_pos(pos) + local rmt_nvm = techage.get_nvm(rmt_pos) + if techage.is_operational(rmt_nvm) then + local tube_dir = M(rmt_pos):get_int("tube_dir") + if techage.push_items(rmt_pos, tube_dir, stack) then + State:keep_running(pos, nvm, COUNTDOWN_TICKS) + State:keep_running(rmt_pos, rmt_nvm, COUNTDOWN_TICKS) + return true + end + else + State:blocked(pos, nvm, S("Remote node error")) + end + end + return false + end, + is_pusher = true, -- is a pulling/pushing node + + on_recv_message = function(pos, src, topic, payload) + if topic == "count" then + local nvm = techage.get_nvm(pos) + return nvm.counter or 0 + elseif topic == "reset" then + local nvm = techage.get_nvm(pos) + nvm.counter = 0 + return true + else + return "unsupported" + end + end, +}) + +power.register_nodes({"techage:ta5_tele_tube"}, Cable, "con", {"B", "R", "F", "D", "U"}) +Tube:set_valid_sides("techage:ta5_tele_tube", {"L"}) + diff --git a/textures/techage_appl_wifi.png b/textures/techage_appl_wifi.png new file mode 100644 index 0000000000000000000000000000000000000000..1a18d594730e5058ac03a116f03e2578a525d78f GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnL3?x0byx0z;*aCb)T-^(NeCp4xzM*{(D8g70 zBN5qp|AfXBqaX-&reABcc8wZaqr)U%xq=9?fE5c zy!x+dVDM)GyH@1^K9xTEwwDaTLP8Er8yP(edm_N*7(!O@Y|0yLJv)78&q Iol`;+0Av<5BLDyZ literal 0 HcmV?d00001