--[[ TechAge ======= Copyright (C) 2019-2025 Joachim Stolberg AGPL v3 See LICENSE.txt for more information Traffic Lights ]]-- local S = techage.S local M = minetest.get_meta local P2S = minetest.pos_to_string local TITLE = S("TA4 Traffic Light") local ConvertTo = { off = { ["techage:ta4_trafficlight1_red"] = "techage:ta4_trafficlight1", ["techage:ta4_trafficlight1_amber"] = "techage:ta4_trafficlight1", ["techage:ta4_trafficlight1_green"] = "techage:ta4_trafficlight1", ["techage:ta4_trafficlight1B_red"] = "techage:ta4_trafficlight1B", ["techage:ta4_trafficlight1B_amber"] = "techage:ta4_trafficlight1B", ["techage:ta4_trafficlight1B_green"] = "techage:ta4_trafficlight1B", ["techage:ta4_trafficlight2_red"] = "techage:ta4_trafficlight2", ["techage:ta4_trafficlight2_amber"] = "techage:ta4_trafficlight2", ["techage:ta4_trafficlight2_green"] = "techage:ta4_trafficlight2", ["techage:ta4_trafficlight2B_red"] = "techage:ta4_trafficlight2B", ["techage:ta4_trafficlight2B_amber"] = "techage:ta4_trafficlight2B", ["techage:ta4_trafficlight2B_green"] = "techage:ta4_trafficlight2B", }, green = { ["techage:ta4_trafficlight1_red"] = "techage:ta4_trafficlight1_green", ["techage:ta4_trafficlight1_amber"] = "techage:ta4_trafficlight1_green", ["techage:ta4_trafficlight1"] = "techage:ta4_trafficlight1_green", ["techage:ta4_trafficlight1B_red"] = "techage:ta4_trafficlight1B_green", ["techage:ta4_trafficlight1B_amber"] = "techage:ta4_trafficlight1B_green", ["techage:ta4_trafficlight1B"] = "techage:ta4_trafficlight1B_green", ["techage:ta4_trafficlight2_red"] = "techage:ta4_trafficlight2_green", ["techage:ta4_trafficlight2_amber"] = "techage:ta4_trafficlight2_green", ["techage:ta4_trafficlight2"] = "techage:ta4_trafficlight2_green", ["techage:ta4_trafficlight2B_red"] = "techage:ta4_trafficlight2B_green", ["techage:ta4_trafficlight2B_amber"] = "techage:ta4_trafficlight2B_green", ["techage:ta4_trafficlight2B"] = "techage:ta4_trafficlight2B_green", }, amber = { ["techage:ta4_trafficlight1_red"] = "techage:ta4_trafficlight1_amber", ["techage:ta4_trafficlight1_green"] = "techage:ta4_trafficlight1_amber", ["techage:ta4_trafficlight1"] = "techage:ta4_trafficlight1_amber", ["techage:ta4_trafficlight1B_red"] = "techage:ta4_trafficlight1B_amber", ["techage:ta4_trafficlight1B_green"] = "techage:ta4_trafficlight1B_amber", ["techage:ta4_trafficlight1B"] = "techage:ta4_trafficlight1B_amber", ["techage:ta4_trafficlight2_red"] = "techage:ta4_trafficlight2_amber", ["techage:ta4_trafficlight2_green"] = "techage:ta4_trafficlight2_amber", ["techage:ta4_trafficlight2"] = "techage:ta4_trafficlight2_amber", ["techage:ta4_trafficlight2B_red"] = "techage:ta4_trafficlight2B_amber", ["techage:ta4_trafficlight2B_green"] = "techage:ta4_trafficlight2B_amber", ["techage:ta4_trafficlight2B"] = "techage:ta4_trafficlight2B_amber", }, red = { ["techage:ta4_trafficlight1_amber"] = "techage:ta4_trafficlight1_red", ["techage:ta4_trafficlight1_green"] = "techage:ta4_trafficlight1_red", ["techage:ta4_trafficlight1"] = "techage:ta4_trafficlight1_red", ["techage:ta4_trafficlight1B_amber"] = "techage:ta4_trafficlight1B_red", ["techage:ta4_trafficlight1B_green"] = "techage:ta4_trafficlight1B_red", ["techage:ta4_trafficlight1B"] = "techage:ta4_trafficlight1B_red", ["techage:ta4_trafficlight2_amber"] = "techage:ta4_trafficlight2_red", ["techage:ta4_trafficlight2_green"] = "techage:ta4_trafficlight2_red", ["techage:ta4_trafficlight2"] = "techage:ta4_trafficlight2_red", ["techage:ta4_trafficlight2B_amber"] = "techage:ta4_trafficlight2B_red", ["techage:ta4_trafficlight2B_green"] = "techage:ta4_trafficlight2B_red", ["techage:ta4_trafficlight2B"] = "techage:ta4_trafficlight2B_red", }, } local function is_pole(pos) local node = minetest.get_node(pos) local dir = tubelib2.side_to_dir("B", node.param2) local pos2 = tubelib2.get_pos(pos, dir) local name = minetest.get_node(pos2).name return name == "techage:trafficlight_connector" or name == "techage:trafficlight_pole" end local function switch_on(pos, color) local node = techage.get_node_lvm(pos) if ConvertTo[color][node.name] then node.name = ConvertTo[color][node.name] M(pos):set_string("state", color) minetest.swap_node(pos, node) end end local function switch_off(pos) local node = techage.get_node_lvm(pos) if ConvertTo["off"][node.name] then node.name = ConvertTo["off"][node.name] M(pos):set_string("state", "off") minetest.swap_node(pos, node) end end local function on_rightclick(pos, node, clicker) if not minetest.is_protected(pos, clicker:get_player_name()) then local state = M(pos):get_string("state") if state == "off" then switch_on(pos, "green") else switch_off(pos) end end end local function after_dig_node(pos, oldnode, oldmetadata) techage.remove_node(pos, oldnode, oldmetadata) end minetest.register_node("techage:ta4_trafficlight1", { description = TITLE, tiles = {"techage_trafficlight1.png"}, drawtype = "mesh", mesh = "techage_traffic_light.obj", after_place_node = function(pos, placer) local number if is_pole(pos) then local node = minetest.get_node(pos) node.name = "techage:ta4_trafficlight1B" minetest.swap_node(pos, node) number = techage.add_node(pos, "techage:ta4_trafficlight1B") else number = techage.add_node(pos, "techage:ta4_trafficlight1") end local meta = M(pos) meta:set_string("state", "off") meta:set_string("infotext", TITLE .. " " .. number) end, on_rightclick = on_rightclick, after_dig_node = after_dig_node, paramtype = "light", use_texture_alpha = techage.CLIP, light_source = 0, sunlight_propagates = true, paramtype2 = "facedir", groups = {cracky=2, crumbly=2}, is_ground_content = false, sounds = default.node_sound_glass_defaults(), }) for _,color in ipairs({"green", "amber", "red"}) do tiles = {"techage_trafficlight1_" .. color .. '.png'} minetest.register_node("techage:ta4_trafficlight1_" .. color, { description = TITLE, tiles = tiles, drawtype = "mesh", mesh = "techage_traffic_light.obj", on_rightclick = on_rightclick, after_dig_node = after_dig_node, paramtype = "light", use_texture_alpha = techage.CLIP, light_source = 10, sunlight_propagates = true, paramtype2 = "facedir", groups = {crumbly=0, not_in_creative_inventory=1}, is_ground_content = false, sounds = default.node_sound_glass_defaults(), drop = "techage:ta4_trafficlight1", }) end minetest.register_node("techage:ta4_trafficlight1B", { description = TITLE, tiles = {"techage_trafficlight1.png"}, drawtype = "mesh", mesh = "techage_traffic_lightB.obj", on_rightclick = on_rightclick, after_dig_node = after_dig_node, paramtype = "light", use_texture_alpha = techage.CLIP, light_source = 0, sunlight_propagates = true, paramtype2 = "facedir", groups = {cracky=2, crumbly=2, not_in_creative_inventory=1}, is_ground_content = false, sounds = default.node_sound_glass_defaults(), drop = "techage:ta4_trafficlight1", }) for _,color in ipairs({"green", "amber", "red"}) do tiles = {"techage_trafficlight1_" .. color .. '.png'} minetest.register_node("techage:ta4_trafficlight1B_" .. color, { description = TITLE, tiles = tiles, drawtype = "mesh", mesh = "techage_traffic_lightB.obj", on_rightclick = on_rightclick, after_dig_node = after_dig_node, paramtype = "light", use_texture_alpha = techage.CLIP, light_source = 10, sunlight_propagates = true, paramtype2 = "facedir", groups = {crumbly=0, not_in_creative_inventory=1}, is_ground_content = false, sounds = default.node_sound_glass_defaults(), drop = "techage:ta4_trafficlight1", }) end minetest.register_node("techage:ta4_trafficlight2", { description = TITLE, tiles = {"techage_trafficlight2.png"}, drawtype = "mesh", mesh = "techage_traffic_light.obj", after_place_node = function(pos, placer) local number if is_pole(pos) then local node = minetest.get_node(pos) node.name = "techage:ta4_trafficlight2B" minetest.swap_node(pos, node) number = techage.add_node(pos, "techage:ta4_trafficlight2B") else number = techage.add_node(pos, "techage:ta4_trafficlight2") end local meta = M(pos) meta:set_string("state", "off") meta:set_string("infotext", TITLE .. " " .. number) end, on_rightclick = on_rightclick, after_dig_node = after_dig_node, paramtype = "light", use_texture_alpha = techage.CLIP, light_source = 0, sunlight_propagates = true, paramtype2 = "facedir", groups = {cracky=2, crumbly=2}, is_ground_content = false, sounds = default.node_sound_glass_defaults(), }) for _,color in ipairs({"green", "amber", "red"}) do tiles = {"techage_trafficlight2_" .. color .. '.png'} minetest.register_node("techage:ta4_trafficlight2_" .. color, { description = TITLE, tiles = tiles, drawtype = "mesh", mesh = "techage_traffic_light.obj", on_rightclick = on_rightclick, after_dig_node = after_dig_node, paramtype = "light", use_texture_alpha = techage.CLIP, light_source = 10, sunlight_propagates = true, paramtype2 = "facedir", groups = {crumbly=0, not_in_creative_inventory=1}, is_ground_content = false, sounds = default.node_sound_glass_defaults(), drop = "techage:ta4_trafficlight2", }) end minetest.register_node("techage:ta4_trafficlight2B", { description = TITLE, tiles = {"techage_trafficlight2.png"}, drawtype = "mesh", mesh = "techage_traffic_lightB.obj", on_rightclick = on_rightclick, after_dig_node = after_dig_node, paramtype = "light", use_texture_alpha = techage.CLIP, light_source = 0, sunlight_propagates = true, paramtype2 = "facedir", groups = {cracky=2, crumbly=2, not_in_creative_inventory=1}, is_ground_content = false, sounds = default.node_sound_glass_defaults(), drop = "techage:ta4_trafficlight1", }) for _,color in ipairs({"green", "amber", "red"}) do tiles = {"techage_trafficlight2_" .. color .. '.png'} minetest.register_node("techage:ta4_trafficlight2B_" .. color, { description = TITLE, tiles = tiles, drawtype = "mesh", mesh = "techage_traffic_lightB.obj", on_rightclick = on_rightclick, after_dig_node = after_dig_node, paramtype = "light", use_texture_alpha = techage.CLIP, light_source = 10, sunlight_propagates = true, paramtype2 = "facedir", groups = {crumbly=0, not_in_creative_inventory=1}, is_ground_content = false, sounds = default.node_sound_glass_defaults(), drop = "techage:ta4_trafficlight2", }) end minetest.register_craft({ output = "techage:ta4_trafficlight1", recipe = { {"", "dye:black", ""}, {"", "techage:ta4_signaltower", ""}, {"", "default:steel_ingot", ""}, }, }) minetest.register_craft({ output = "techage:ta4_trafficlight2", recipe = { {"", "dye:orange", ""}, {"", "techage:ta4_signaltower", ""}, {"", "default:steel_ingot", ""}, }, }) techage.register_node({ "techage:ta4_trafficlight1", "techage:ta4_trafficlight1_green", "techage:ta4_trafficlight1_amber", "techage:ta4_trafficlight1_red", "techage:ta4_trafficlight2", "techage:ta4_trafficlight2_green", "techage:ta4_trafficlight2_amber", "techage:ta4_trafficlight2_red", "techage:ta4_trafficlight1B", "techage:ta4_trafficlight1B_green", "techage:ta4_trafficlight1B_amber", "techage:ta4_trafficlight1B_red", "techage:ta4_trafficlight2B", "techage:ta4_trafficlight2B_green", "techage:ta4_trafficlight2B_amber", "techage:ta4_trafficlight2B_red"}, { on_recv_message = function(pos, src, topic, payload) if topic == "green" then switch_on(pos, "green") elseif topic == "amber" then switch_on(pos, "amber") elseif topic == "red" then switch_on(pos, "red") elseif topic == "off" then switch_off(pos) elseif topic == "state" then local meta = minetest.get_meta(pos) return meta:get_string("state") end end, on_beduino_receive_cmnd = function(pos, src, topic, payload) if topic == 2 then local color = ({"green", "amber", "red"})[payload[1]] if color then switch_on(pos, color) else switch_off(pos) end return 0 else return 2 -- unknown or invalid topic end end, on_beduino_request_data = function(pos, src, topic, payload) if topic == 130 then local meta = minetest.get_meta(pos) local color = ({off = 0, green = 1, amber = 2, red = 3})[meta:get_string("state")] or 1 return 0, {color} else return 2, "" -- unknown or invalid topic end end, }) minetest.register_node("techage:trafficlight_pole", { description = S("TA4 Traffic Light Pole"), tiles = { "techage_trafficlight_pole.png", }, paramtype2 = "facedir", -- important! drawtype = "nodebox", node_box = { type = "connected", fixed = {{ -4/32, -16/32, -4/32, 4/32, 16/32, 4/32}}, connect_left = {{-16/32, 0/32, -3/32, 3/32, 6/32, 3/32}}, connect_right = {{ -3/32, 0/32, -3/32, 16/32, 6/32, 3/32}}, connect_back = {{ -3/32, 0/32, -3/32, 3/32, 6/32, 16/32}}, connect_front = {{ -3/32, 0/32, -16/32, 3/32, 6/32, 3/32}}, }, connects_to = { "techage:trafficlight_arm", "techage:trafficlight_connector", "techage:ta4_trafficlight1", "techage:ta4_trafficlight1B", "techage:ta4_trafficlight1_red", "techage:ta4_trafficlight1_amber", "techage:ta4_trafficlight1_green", "techage:ta4_trafficlight1B_red", "techage:ta4_trafficlight1B_amber", "techage:ta4_trafficlight1B_green", "techage:ta4_trafficlight2", "techage:ta4_trafficlight2B", "techage:ta4_trafficlight2_red", "techage:ta4_trafficlight2_amber", "techage:ta4_trafficlight2_green", "techage:ta4_trafficlight2B_red", "techage:ta4_trafficlight2B_amber", "techage:ta4_trafficlight2B_green", }, paramtype = "light", sunlight_propagates = true, is_ground_content = false, groups = {cracky=2, crumbly=2, choppy=2}, sounds = default.node_sound_defaults(), }) minetest.register_node("techage:trafficlight_connector", { description = S("TA4 Traffic Light Connector"), tiles = { "techage_trafficlight_pole.png", }, paramtype2 = "facedir", -- important! drawtype = "nodebox", node_box = { type = "connected", fixed = {{ -4/32, -4/32, -4/32, 4/32, 10/32, 4/32}}, connect_left = {{-16/32, 0/32, -3/32, 3/32, 6/32, 3/32}}, connect_right = {{ -3/32, 0/32, -3/32, 16/32, 6/32, 3/32}}, connect_back = {{ -3/32, 0/32, -3/32, 3/32, 6/32, 16/32}}, connect_front = {{ -3/32, 0/32, -16/32, 3/32, 6/32, 3/32}}, }, connects_to = { "techage:trafficlight_arm", "techage:trafficlight_connector", "techage:trafficlight_pole", "techage:ta4_trafficlight1", "techage:ta4_trafficlight1B", "techage:ta4_trafficlight1_red", "techage:ta4_trafficlight1_amber", "techage:ta4_trafficlight1_green", "techage:ta4_trafficlight1B_red", "techage:ta4_trafficlight1B_amber", "techage:ta4_trafficlight1B_green", "techage:ta4_trafficlight2", "techage:ta4_trafficlight2B", "techage:ta4_trafficlight2_red", "techage:ta4_trafficlight2_amber", "techage:ta4_trafficlight2_green", "techage:ta4_trafficlight2B_red", "techage:ta4_trafficlight2B_amber", "techage:ta4_trafficlight2B_green", }, paramtype = "light", sunlight_propagates = true, is_ground_content = false, groups = {cracky=2, crumbly=2, choppy=2}, sounds = default.node_sound_defaults(), }) minetest.register_node("techage:trafficlight_arm", { description = S("TA4 Traffic Light Arm"), tiles = { "techage_trafficlight_pole.png", }, paramtype2 = "facedir", -- important! drawtype = "nodebox", node_box = { type = "fixed", fixed = {{ -3/32, 0/32, -16/32, 3/32, 6/32, 16/32}}, }, paramtype = "light", sunlight_propagates = true, is_ground_content = false, groups = {cracky=2, crumbly=2, choppy=2}, sounds = default.node_sound_defaults(), }) minetest.register_craft({ output = "techage:trafficlight_pole", recipe = { {"", "basic_materials:steel_bar", ""}, {"", "basic_materials:steel_bar", "dye:dark_grey"}, {"", "basic_materials:steel_bar", ""}, }, }) minetest.register_craft({ output = "techage:trafficlight_arm", recipe = { {"", "dye:dark_grey", ""}, {"basic_materials:steel_bar", "basic_materials:steel_bar", "basic_materials:steel_bar"}, {"", "", ""}, }, }) minetest.register_craft({ output = "techage:trafficlight_connector", recipe = { {"dye:dark_grey", "basic_materials:steel_bar", ""}, {"basic_materials:steel_bar", "", ""}, {"", "", ""}, }, })