diff --git a/doc/ta3_doc.lua b/doc/ta3_doc.lua index 38b2e20..01ed2c4 100644 --- a/doc/ta3_doc.lua +++ b/doc/ta3_doc.lua @@ -109,5 +109,5 @@ techage.register_category_page("ta3l", S("TA3: Logic"), S("Collection of TA3 logic blocks to control your machines."), "techage:terminal2", - {"terminal", "button", "detector", "repeater", "programmer"} + {"terminal", "button", "detector", "repeater", "logic", "node_detector", "player_detector", "programmer"} ) diff --git a/init.lua b/init.lua index 6d2c024..db53950 100644 --- a/init.lua +++ b/init.lua @@ -161,6 +161,9 @@ else dofile(MP.."/logic/signallamp.lua") dofile(MP.."/logic/sequencer.lua") dofile(MP.."/logic/timer.lua") + dofile(MP.."/logic/lua_logic.lua") + dofile(MP.."/logic/node_detector.lua") + dofile(MP.."/logic/player_detector.lua") -- Test dofile(MP.."/recipe_checker.lua") diff --git a/logic/button.lua b/logic/button.lua index df36947..9c79885 100644 --- a/logic/button.lua +++ b/logic/button.lua @@ -29,14 +29,16 @@ local function switch_on(pos) }) end -local function switch_off(pos) +local function switch_off(pos, is_button) logic.swap_node(pos, "techage:ta3_button_off") logic.send_off(pos, M(pos)) - minetest.sound_play("techage_button", { - pos = pos, - gain = 0.5, - max_hear_distance = 5, - }) + if not is_button then + minetest.sound_play("techage_button", { + pos = pos, + gain = 0.5, + max_hear_distance = 5, + }) + end end local function formspec(meta) @@ -44,7 +46,7 @@ local function formspec(meta) local idx = meta:get_int("cycle_idx") or 0 if idx == 0 then idx = 1 end return "size[7.5,6]".. - "dropdown[0.2,0;3;type;switch,button 2s,button 4s,button 8s,button 16s,button 32s;"..idx.."]".. + "dropdown[0.2,0;3;type;switch,button 1s,button 2s,button 4s,button 8s,button 16s,button 32s;"..idx.."]".. "field[0.5,2;7,1;numbers;"..S("Insert destination node number(s)")..";"..numbers.."]" .. "checkbox[1,3;public;public;false]".. "button_exit[2,4;3,1;exit;"..S("Save").."]" @@ -88,20 +90,23 @@ minetest.register_node("techage:ta3_button_off", { if fields.type == "switch" then meta:set_int("cycle_idx", 1) cycle_time = 0 - elseif fields.type == "button 2s" then + elseif fields.type == "button 1s" then meta:set_int("cycle_idx", 2) + cycle_time = 1 + elseif fields.type == "button 2s" then + meta:set_int("cycle_idx", 3) cycle_time = 2 elseif fields.type == "button 4s" then - meta:set_int("cycle_idx", 3) + meta:set_int("cycle_idx", 4) cycle_time = 4 elseif fields.type == "button 8s" then - meta:set_int("cycle_idx", 4) + meta:set_int("cycle_idx", 5) cycle_time = 8 elseif fields.type == "button 16s" then - meta:set_int("cycle_idx", 5) + meta:set_int("cycle_idx", 6) cycle_time = 16 elseif fields.type == "button 32s" then - meta:set_int("cycle_idx", 6) + meta:set_int("cycle_idx", 7) cycle_time = 32 end if cycle_time ~= nil then diff --git a/logic/lib.lua b/logic/lib.lua index 4d3fa18..dff1792 100644 --- a/logic/lib.lua +++ b/logic/lib.lua @@ -18,13 +18,35 @@ local S = techage.S techage.logic = {} +local Face2Dir = {[0]= + {x=0, y=0, z=1}, + {x=1, y=0, z=0}, + {x=0, y=0, z=-1}, + {x=-1, y=0, z=0}, + {x=0, y=-1, z=0}, + {x=0, y=1, z=0} +} + +-- Determine the destination position based on the position, +-- the node param2, and a route table like : {0,0,3} +-- 0 = forward, 1 = right, 2 = backward, 3 = left +function techage.logic.dest_pos(pos, param2, route) + local p2 = param2 + for _,dir in ipairs(route) do + p2 = (param2 + dir) % 4 + pos = vector.add(pos, Face2Dir[p2]) + end + return pos, p2 +end + function techage.logic.swap_node(pos, name) local node = minetest.get_node(pos) if node.name == name then - return + return false end node.name = name minetest.swap_node(pos, node) + return true end function techage.logic.after_place_node(pos, placer, name, descr) diff --git a/logic/lua_logic.lua b/logic/lua_logic.lua new file mode 100644 index 0000000..e99fd48 --- /dev/null +++ b/logic/lua_logic.lua @@ -0,0 +1,260 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2017-2019 Joachim Stolberg + + GPL v3 + See LICENSE.txt for more information + + Lua Logic Block + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S +local logic = techage.logic + +-- mem.inp_tbl = { +-- n001 = true, -- "on" received +-- n002 = false, -- "off" received +-- inp = true, -- last input +-- outp = false, -- last output +-- } + +local ValidSymbols = { + ["if"] = true, + ["then"] = true, + ["else"] = true, + ["end"] = true, + ["return"] = true, + ["not"] = true, + ["and"] = true, + ["or"] = true, + ["inp"] = true, + ["outp"] = true, + ["true"] = true, + ["false"] = true, + ["nil"] = true, + ["=="] = true, + ["~="] = true, + ["("] = true, + [")"] = true, +} +local function check(expression) + for _, sym in ipairs(string.split(expression, " ")) do + if not ValidSymbols[sym] and string.find(sym, '^[n0-9]+$') == nil then + return false, "Error: Invalid symbol '"..sym.."'" + end + end + return true, "ok" +end + +local function compile(mem, expression) + local res, err = check(expression) + if res then + local code, err = loadstring(expression, "") + if code then + mem.code = code + mem.error = "ok" + else + mem.code = nil + mem.error = err + end + else + mem.code = nil + mem.error = err + end +end + +local function get_code(pos, mem) + local meta = M(pos) + local if_expr = meta:get_string("if_expr") or "" + local then_expr = meta:get_string("then_expr") or "" + local else_expr = meta:get_string("else_expr") or "" + local expr = "if "..if_expr.." then return "..then_expr.." else return "..else_expr.." end" + compile(mem, expr) + return mem.code +end + +local function eval(pos, mem) + mem.code = mem.code or get_code(pos, mem) + if mem.code then + setfenv(mem.code, mem.inp_tbl) + local res, sts = pcall(mem.code) + if res then + mem.error = "ok" + if sts == true then + mem.inp_tbl.outp = sts + return "on" + elseif sts == false then + mem.inp_tbl.outp = sts + return "off" + end + else + mem.error = "Error: "..sts + end + end +end + +local function data(mem) + local tbl = {"inp = "..dump(mem.inp_tbl.inp), "outp = "..dump(mem.inp_tbl.outp)} + for k,v in pairs(mem.inp_tbl) do + if k ~= "inp" and k ~= "outp" then + tbl[#tbl+1] = k.." = "..dump(v) + end + end + return table.concat(tbl, ", ") +end + +local function formspec(pos, meta) + local mem = tubelib2.get_mem(pos) + local numbers = meta:get_string("numbers") or "" + local if_expr = meta:get_string("if_expr") or "" + local then_expr = meta:get_string("then_expr") or "" + local else_expr = meta:get_string("else_expr") or "" + local err = mem.error or "ok" + if err ~= "ok" then + err = string.sub(err, 15) + end + err = minetest.formspec_escape(err) + mem.inp_tbl = mem.inp_tbl or {inp = false, outp = false} + local data = data(mem) + return "size[9,8]".. + "background[0,0;9,1.3;techage_formspec_bg.png]".. + "field[0.5,0.2;8.5,2;numbers;"..S(" Insert destination node number(s)")..";"..numbers.."]" .. + "label[0,1.4;Variables: "..data.."]".. + "label[0,2;Valid symbols: not and or true false nil == ~= ( )]".. + "background[0,2.6;9,4;techage_formspec_bg.png]".. + "label[0.1,2.8;if]".. + "field[0.8,2.9;7,1;if_expr;;"..if_expr.."]" .. + "label[7.6,2.8;then]".. + "label[0.6,3.8;return]".. + "field[2,3.9;7,1;then_expr;;"..then_expr.."]" .. + "label[0.1,4.5;else]".. + "label[0.6,5.2;return]".. + "field[2,5.3;7,1;else_expr;;"..else_expr.."]" .. + "label[0.1,6;end]".. + "label[0,6.8;Result: "..err.."]".. + "button[2,7.3;2.5,1;update;"..S("Update").."]".. + "button[5,7.3;2.5,1;store;"..S("Store").."]" +end + +minetest.register_node("techage:ta3_logic", { + description = S("TA3 Logic Block"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta3.png^techage_frame_ta3_top.png", + "techage_filling_ta3.png^techage_frame_ta3_top.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_logic.png", + }, + + after_place_node = function(pos, placer) + local meta = M(pos) + local mem = tubelib2.init_mem(pos) + mem.inp_tbl = {inp = false, outp = false} + logic.after_place_node(pos, placer, "techage:ta3_logic", S("TA3 Logic Block")) + logic.infotext(meta, S("TA3 Logic Block")) + meta:set_string("formspec", formspec(pos, meta)) + end, + + on_receive_fields = function(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + + local meta = M(pos) + local mem = tubelib2.get_mem(pos) + if fields.numbers and fields.numbers ~= "" then + if techage.check_numbers(fields.numbers, player:get_player_name()) then + meta:set_string("numbers", fields.numbers) + logic.infotext(M(pos), S("TA3 Logic Block")) + end + end + if fields.if_expr and fields.if_expr ~= "" then + meta:set_string("if_expr", fields.if_expr) + end + if fields.then_expr and fields.then_expr ~= "" then + meta:set_string("then_expr", fields.then_expr) + end + if fields.else_expr and fields.else_expr ~= "" then + meta:set_string("else_expr", fields.else_expr) + end + if fields.store then + get_code(pos, mem) + end + meta:set_string("formspec", formspec(pos, meta)) + end, + + on_timer = function(pos,elapsed) + local mem = tubelib2.get_mem(pos) + local topic = eval(pos, mem) + if topic then + local meta = M(pos) + local own_num = meta:get_string("node_number") or "" + local numbers = meta:get_string("numbers") or "" + techage.send_multi(own_num, numbers, topic) + end + return false + end, + + techage_set_numbers = function(pos, numbers, player_name) + local meta = M(pos) + local res = logic.set_numbers(pos, numbers, player_name, S("TA3 Logic Block")) + meta:set_string("formspec", formspec(pos, meta)) + return res + end, + + after_dig_node = function(pos) + techage.remove_node(pos) + tubelib2.del_mem(pos) + end, + + paramtype2 = "facedir", + groups = {choppy=2, cracky=2, crumbly=2}, + is_ground_content = false, + sounds = default.node_sound_wood_defaults(), +}) + + +minetest.register_craft({ + output = "techage:ta3_logic", + recipe = { + {"", "group:wood", ""}, + {"", "default:copper_ingot", "techage:vacuum_tube"}, + {"", "group:wood", ""}, + }, +}) + +techage.register_node({"techage:ta3_logic"}, { + on_recv_message = function(pos, src, topic, payload) + local mem = tubelib2.get_mem(pos) + mem.inp_tbl = mem.inp_tbl or {outp = false} + + if topic == "on" then + mem.inp_tbl.inp = true + mem.inp_tbl["n"..src] = true + elseif topic == "off" then + mem.inp_tbl.inp = false + mem.inp_tbl["n"..src] = false + else + return + end + minetest.get_node_timer(pos):start(0.1) + end, + on_node_load = function(pos) + + end, +}) + +techage.register_entry_page("ta3l", "logic", + S("TA3 Logic Block"), + S("The Logic Block is used to combine one or several input signals@n".. + "by means of a boolean expression into one output signal,@n".. + "like 'n123 and n345', 'not n123', or simply 'inp'.@n".. + "The then-part and the else-part are used to set the output.@n".. + "true means 'on', false means 'off', nothing means send nothing."), + "techage:ta3_logic") + diff --git a/logic/node_detector.lua b/logic/node_detector.lua new file mode 100644 index 0000000..6e01e10 --- /dev/null +++ b/logic/node_detector.lua @@ -0,0 +1,201 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2017-2019 Joachim Stolberg + + GPL v3 + See LICENSE.txt for more information + + Node Detector + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S + +local logic = techage.logic +local CYCLE_TIME = 4 + +local function switch_on(pos) + if logic.swap_node(pos, "techage:ta3_nodedetector_on") then + logic.send_on(pos, M(pos)) + end +end + +local function switch_off(pos) + if logic.swap_node(pos, "techage:ta3_nodedetector_off") then + logic.send_off(pos, M(pos)) + end +end + +local DropdownValues = { + [S("added")] = 1, + [S("removed")] = 2, + [S("added or removed")] = 3, +} + +local function formspec(meta, mem) + local numbers = meta:get_string("numbers") or "" + local label = S("added")..","..S("removed")..","..S("added or removed") + return "size[7.5,4]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "field[0.5,0.6;7,1;numbers;"..S("Insert destination node number(s)")..";"..numbers.."]" .. + "label[0.2,1.6;"..S("Send signal if nodes have been:").."]".. + "dropdown[0.2,2.1;7.3,1;mode;"..label..";"..(mem.mode or 3).."]".. + "button_exit[2,3.2;3,1;accept;"..S("accept").."]" +end + +local function any_node_changed(pos) + local mem = tubelib2.get_mem(pos) + if not mem.pos1 or not mem.pos2 or not mem.num then + local node = minetest.get_node(pos) + local param2 = (node.param2 + 2) % 4 + mem.pos1 = logic.dest_pos(pos, param2, {0}) + mem.pos2 = logic.dest_pos(pos, param2, {0,0,0}) + mem.num = #minetest.find_nodes_in_area(mem.pos1, mem.pos2, {"air"}) + return false + end + local num = #minetest.find_nodes_in_area(mem.pos1, mem.pos2, {"air"}) + + if mem.num ~= num then + if mem.mode == 1 and num < mem.num then + mem.num = num + return true + elseif mem.mode == 2 and num > mem.num then + mem.num = num + return true + elseif mem.mode == 3 then + mem.num = num + return true + end + mem.num = num + end + return false +end + +local function on_receive_fields(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + + local mem = tubelib2.get_mem(pos) + local meta = M(pos) + if fields.accept then + mem.mode = DropdownValues[fields.mode] or 3 + if techage.check_numbers(fields.numbers, player:get_player_name()) then + meta:set_string("numbers", fields.numbers) + logic.infotext(M(pos), S("TA3 Node Detector")) + end + end + meta:set_string("formspec", formspec(meta, mem)) +end + +local function node_timer(pos) + if any_node_changed(pos)then + switch_on(pos) + else + switch_off(pos) + end + return true +end + +minetest.register_node("techage:ta3_nodedetector_off", { + description = S("TA3 Node Detector"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta3.png^techage_frame_ta3_top.png^techage_appl_arrow.png^[transformR270", + "techage_filling_ta3.png^techage_frame_ta3_top.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_nodedetector.png", + }, + + after_place_node = function(pos, placer) + local meta = M(pos) + local mem = tubelib2.init_mem(pos) + logic.after_place_node(pos, placer, "techage:ta3_repeater", S("TA3 Node Detector")) + logic.infotext(meta, S("TA3 Node Detector")) + mem.mode = 3 -- default mode + meta:set_string("formspec", formspec(meta, mem)) + minetest.get_node_timer(pos):start(CYCLE_TIME) + any_node_changed(pos) + end, + + on_timer = node_timer, + on_receive_fields = on_receive_fields, + + techage_set_numbers = function(pos, numbers, player_name) + local meta = M(pos) + local res = logic.set_numbers(pos, numbers, player_name, S("TA3 Node Detector")) + meta:set_string("formspec", formspec(meta, tubelib2.get_mem(pos))) + return res + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + techage.remove_node(pos) + tubelib2.del_mem(pos) + end, + + on_rotate = screwdriver.disallow, + paramtype2 = "facedir", + is_ground_content = false, + groups = {choppy=2, cracky=2, crumbly=2}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_node("techage:ta3_nodedetector_on", { + description = S("TA3 Node Detector"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta3.png^techage_frame_ta3_top.png^techage_appl_arrow.png^[transformR270", + "techage_filling_ta3.png^techage_frame_ta3_top.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_nodedetector_on.png", + }, + + on_timer = node_timer, + + techage_set_numbers = function(pos, numbers, player_name) + local meta = M(pos) + local res = logic.set_numbers(pos, numbers, player_name, S("TA3 Node Detector")) + meta:set_string("formspec", formspec(meta, tubelib2.get_mem(pos))) + return res + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + techage.remove_node(pos) + tubelib2.del_mem(pos) + end, + + on_rotate = screwdriver.disallow, + paramtype2 = "facedir", + is_ground_content = false, + drop = "techage:ta3_nodedetector_off", + groups = {choppy=2, cracky=2, crumbly=2, not_in_creative_inventory = 1}, + sounds = default.node_sound_wood_defaults(), +}) + +minetest.register_craft({ + output = "techage:ta3_nodedetector_off", + recipe = { + {"", "group:wood", ""}, + {"", "default:copper_ingot", "techage:vacuum_tube"}, + {"", "group:wood", "default:mese_crystal"}, + }, +}) + +techage.register_node({"techage:ta3_nodedetector_off", "techage:ta3_nodedetector_on"}, { + on_node_load = function(pos) + minetest.get_node_timer(pos):start(CYCLE_TIME) + end, +}) + +techage.register_entry_page("ta3l", "node_detector", + S("TA3 Node Detector"), + S("The Node Detector can send a 'on' signal when it detects that nodes appear@n".. + "or disappear, but has to be configured accordingly.@n".. + "Valid nodes are all kind of blocks and plants.@n".. + "The sensor range is 3 nodes/meters in the arrow direction."), + "techage:ta3_nodedetector_on") diff --git a/logic/player_detector.lua b/logic/player_detector.lua new file mode 100644 index 0000000..d553b3d --- /dev/null +++ b/logic/player_detector.lua @@ -0,0 +1,206 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2017-2019 Joachim Stolberg + + GPL v3 + See LICENSE.txt for more information + + Player Detector + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S + +local logic = techage.logic +local CYCLE_TIME = 1 + +local function switch_on(pos) + if logic.swap_node(pos, "techage:ta3_playerdetector_on") then + logic.send_on(pos, M(pos)) + end +end + +local function switch_off(pos) + if logic.swap_node(pos, "techage:ta3_playerdetector_off") then + logic.send_off(pos, M(pos)) + end +end + +local function scan_for_player(pos) + local mem = tubelib2.get_mem(pos) + local meta = minetest.get_meta(pos) + local names = meta:get_string("names") or "" + for _, object in pairs(minetest.get_objects_inside_radius(pos, 4)) do + if object:is_player() then + if names == "" then + mem.player_name = object:get_player_name() + return true + end + for _,name in ipairs(string.split(names, " ")) do + if object:get_player_name() == name then + mem.player_name = name + return true + end + end + end + end + mem.player_name = nil + return false +end + +local function formspec_help() + return "size[8,6]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "label[3,0;Player Detector Help]".. + "label[0,1;Input the number(s) of the destination node(s).\n".. + "Separate numbers via blanks, like '123 234'.\n\n".. + "Input the player name(s) separated by blanks,\nor empty for all players.]".. + "button_exit[3,5;2,1;exit;close]" +end + + +local function formspec(meta) + local numbers = meta:get_string("numbers") or "" + local names = meta:get_string("names") or "" + return "size[7,4]".. + default.gui_bg.. + default.gui_bg_img.. + default.gui_slots.. + "field[0.3,0.6;7,1;numbers;"..S("Insert destination node number(s)")..";"..numbers.."]" .. + "field[0.3,2;7,1;names;Insert player name(s) (optional):;"..names.."]" .. + "button[0.9,3;2.5,1;help;help]".. + "button_exit[3.5,3;2.5,1;exit;Save]" +end + +local function on_receive_fields(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + + local meta = minetest.get_meta(pos) + if fields.exit == "Save" then + if techage.check_numbers(fields.numbers, player:get_player_name()) then + meta:set_string("numbers", fields.numbers) + logic.infotext(M(pos), S("TA3 Player Detector")) + end + meta:set_string("formspec", formspec(meta)) + elseif fields.help ~= nil then + meta:set_string("formspec", formspec_help()) + elseif fields.exit == "close" then + meta:set_string("formspec", formspec(meta)) + end +end + +minetest.register_node("techage:ta3_playerdetector_off", { + description = S("TA3 Player Detector"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta3.png^techage_frame_ta3_top.png", + "techage_filling_ta3.png^techage_frame_ta3_top.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_playerdetector.png", + }, + after_place_node = function(pos, placer) + local meta = M(pos) + logic.after_place_node(pos, placer, "techage:ta3_playerdetector_off", S("TA3 Player Detector")) + logic.infotext(meta, S("TA3 Player Detector")) + meta:set_string("formspec", formspec(meta)) + minetest.get_node_timer(pos):start(CYCLE_TIME) + end, + + on_receive_fields = on_receive_fields, + + on_timer = function (pos, elapsed) + if scan_for_player(pos) then + switch_on(pos) + end + return true + end, + + techage_set_numbers = function(pos, numbers, player_name) + local meta = M(pos) + local res = logic.set_numbers(pos, numbers, player_name, S("TA3 Player Detector")) + meta:set_string("formspec", formspec(meta)) + return res + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + techage.remove_node(pos) + tubelib2.del_mem(pos) + end, + + paramtype2 = "facedir", + groups = {choppy=2, cracky=2, crumbly=2}, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), +}) + +minetest.register_node("techage:ta3_playerdetector_on", { + description = "TA3 Player Detector", + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta3.png^techage_frame_ta3_top.png", + "techage_filling_ta3.png^techage_frame_ta3_top.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_playerdetector_on.png", + }, + on_receive_fields = on_receive_fields, + + on_timer = function (pos, elapsed) + if not scan_for_player(pos) then + switch_off(pos) + end + return true + end, + + techage_set_numbers = function(pos, numbers, player_name) + local meta = M(pos) + local res = logic.set_numbers(pos, numbers, player_name, S("TA3 Player Detector")) + meta:set_string("formspec", formspec(meta)) + return res + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + techage.remove_node(pos) + tubelib2.del_mem(pos) + end, + + paramtype2 = "facedir", + groups = {choppy=2, cracky=2, crumbly=2, not_in_creative_inventory=1}, + is_ground_content = false, + sounds = default.node_sound_wood_defaults(), + drop = "techage:ta3_playerdetector_off" +}) + +minetest.register_craft({ + output = "techage:ta3_playerdetector_off", + recipe = { + {"", "group:wood", "default:mese_crystal"}, + {"", "default:copper_ingot", "techage:vacuum_tube"}, + {"", "group:wood", ""}, + }, +}) + +techage.register_node({"techage:ta3_playerdetector_off", "techage:ta3_playerdetector_on"}, { + on_recv_message = function(pos, topic, payload) + if topic == "name" then + local mem = tubelib2.get_mem(pos) + return mem.player_name or "" + end + end, + on_node_load = function(pos) + minetest.get_node_timer(pos):start(CYCLE_TIME) + end, +}) + +techage.register_entry_page("ta3l", "player_detector", + S("TA3 Player Detector"), + S("The Player Detector sends a 'on' signal when it detects a player@n".. + "within a radius of 4 m around the node.@n".. + "The detector can be configured with player names to scan for."), + "techage:ta3_playerdetector_on") diff --git a/logic/repeater.lua b/logic/repeater.lua index c76d175..d5784cd 100644 --- a/logic/repeater.lua +++ b/logic/repeater.lua @@ -47,6 +47,10 @@ minetest.register_node("techage:ta3_repeater", { end, on_receive_fields = function(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + local meta = M(pos) if techage.check_numbers(fields.numbers, player:get_player_name()) then meta:set_string("numbers", fields.numbers) @@ -73,12 +77,10 @@ minetest.register_node("techage:ta3_repeater", { tubelib2.del_mem(pos) end, - paramtype = "light", - sunlight_propagates = true, paramtype2 = "facedir", groups = {choppy=2, cracky=2, crumbly=2}, is_ground_content = false, - sounds = default.node_sound_stone_defaults(), + sounds = default.node_sound_wood_defaults(), }) diff --git a/logic/sequencer.lua b/logic/sequencer.lua index 74fe3a2..0b6168d 100644 --- a/logic/sequencer.lua +++ b/logic/sequencer.lua @@ -137,7 +137,7 @@ local function start_the_sequencer(pos) return false end -local function on_receive_fields(pos, formname, fields, player) +local function on_receive_fields(pos, formname, fields, player) if minetest.is_protected(pos, player:get_player_name()) then return end diff --git a/textures/techage_appl_logic.png b/textures/techage_appl_logic.png new file mode 100644 index 0000000..d1611cc Binary files /dev/null and b/textures/techage_appl_logic.png differ diff --git a/textures/techage_appl_nodedetector.png b/textures/techage_appl_nodedetector.png new file mode 100644 index 0000000..7c8f096 Binary files /dev/null and b/textures/techage_appl_nodedetector.png differ diff --git a/textures/techage_appl_nodedetector_on.png b/textures/techage_appl_nodedetector_on.png new file mode 100644 index 0000000..04173ea Binary files /dev/null and b/textures/techage_appl_nodedetector_on.png differ diff --git a/textures/techage_appl_playerdetector.png b/textures/techage_appl_playerdetector.png new file mode 100644 index 0000000..28bf4eb Binary files /dev/null and b/textures/techage_appl_playerdetector.png differ diff --git a/textures/techage_appl_playerdetector_on.png b/textures/techage_appl_playerdetector_on.png new file mode 100644 index 0000000..72389ea Binary files /dev/null and b/textures/techage_appl_playerdetector_on.png differ diff --git a/textures/techage_formspec_bg.png b/textures/techage_formspec_bg.png new file mode 100644 index 0000000..78bba06 Binary files /dev/null and b/textures/techage_formspec_bg.png differ