diff --git a/doc/manual_DE.lua b/doc/manual_DE.lua index 9397be6..72c00ba 100644 --- a/doc/manual_DE.lua +++ b/doc/manual_DE.lua @@ -997,10 +997,18 @@ techage.manual_DE.aText = { "\n".. "\n".. "\n", - "Der Tür Controller II kann alle Arten von Blöcken entfernen und wieder setzen. Um den Tür Controller II anzulernen\\, muss der \"Aufzeichnen\" Button gedrückt werden. Dann müssen alle Blöcke angeklickt werden\\, die Teil der Tür / des Tores sein sollen. Danach muss der \"Fertig\" Button gedrückt werden. Es können bis zu 16 Blöcke ausgewählt werden. Die entfernten Blöcke werden im Inventar des Controllers gespeichert. Über die Tasten \"Entfernen\" bzw. \"Setzen\" kann die Funktion des Controllers von Hand getestet werden.\n".. + "Der Tür Controller II kann alle Arten von Blöcken entfernen und wieder setzen. Um den Tür Controller II anzulernen\\, muss der \"Aufzeichnen\" Button gedrückt werden. Dann müssen alle Blöcke angeklickt werden\\, die Teil der Tür / des Tores sein sollen. Danach muss der \"Fertig\" Button gedrückt werden. Es können bis zu 16 Blöcke ausgewählt werden. Die entfernten Blöcke werden im Inventar des Controllers gespeichert.\n".. + "\n".. + " Über die Tasten \"Entfernen\" bzw. \"Setzen\" kann die Funktion des Controllers von Hand getestet werden.\n".. "\n".. "Wird ein 'on' / 'off' Kommando an den Tür Controller II gesendet\\, entfernt bzw. setzt er die Blöcke ebenfalls.\n".. "\n".. + "Über ein 'exchange' Kommando können einzelne Böcke gesetzt\\, entfernt\\, bzw. durch andere Blöcke ersetzt werden. Die Slot-Nummer des Inventars (1 .. 16) muss als payload übergeben werden\\, also:\n".. + "\n".. + " $send_cmnd(node_number\\, \"exchange\"\\, 2)\n".. + "\n".. + "Damit lassen sich auch ausfahrbare Treppen und ähnliches simulieren.\n".. + "\n".. "\n".. "\n", "Der Mesecons Umsetzer dient zur Umwandlung von Techage on/off Kommandos in Mesecons Signale und umgekehrt.\n".. diff --git a/doc/manual_EN.lua b/doc/manual_EN.lua index 6042ec1..6adc9ff 100644 --- a/doc/manual_EN.lua +++ b/doc/manual_EN.lua @@ -988,6 +988,12 @@ techage.manual_EN.aText = { "\n", "The Door Controller II can remove and set all types of blocks. To teach in the Door Controller II\\, the \"Record\" button must be pressed. Then all blocks that should be part of the door / gate must be clicked. Then the \"Done\" button must be pressed. Up to 16 blocks can be selected. The removed blocks are saved in the controller's inventory. The function of the controller can be tested manually using the \"Remove\" or \"Set\" buttons. If an 'on' /'off' command is sent to the Door Controller II\\, it removes or sets the blocks as well.\n".. "\n".. + "Individual blocks can be set\\, removed or replaced by other blocks via an 'exchange' command. The slot number of the inventory (1 .. 16) must be transferred as payload\\, i.e.:\n".. + "\n".. + " $send_cmnd(node_number\\, \"exchange\"\\, 2)\n".. + "\n".. + "This can also be used to simulate extendable stairs and the like. \n".. + "\n".. "\n".. "\n", "The Mesecons converter is used to convert Techage on/off commands into Mesecons signals and vice versa.\n".. diff --git a/logic/doorcontroller2.lua b/logic/doorcontroller2.lua index d846a5a..817b3c2 100644 --- a/logic/doorcontroller2.lua +++ b/logic/doorcontroller2.lua @@ -3,7 +3,7 @@ TechAge ======= - Copyright (C) 2020 Joachim Stolberg + Copyright (C) 2020-2021 Joachim Stolberg AGPL v3 See LICENSE.txt for more information @@ -19,23 +19,43 @@ local S = techage.S local logic = techage.logic -local MarkedNodes = {} -- t[player][hash] = entity +local MarkedNodes = {} -- t[player] = {{entity, pos},...} local CurrentPos -- to mark punched entities +local RegisteredNodes = {} -- to be checked before removed/placed + +local function is_simple_node(name) + -- special handling + if RegisteredNodes[name] ~= nil then + return RegisteredNodes[name] + end + + local ndef = minetest.registered_nodes[name] + if not ndef or name == "air" then return true end + if ndef.groups and ndef.groups.techage_door == 1 then return true end + + -- don't remove nodes with some intelligence or undiggable nodes + if ndef.drop == "" then return false end + if ndef.diggable == false then return false end + if ndef.after_dig_node then return false end + + return true +end local function unmark_position(name, pos) - MarkedNodes[name] = MarkedNodes[name] or {} pos = vector.round(pos) - local hash = minetest.hash_node_position(pos) - if MarkedNodes[name][hash] then - MarkedNodes[name][hash]:remove() - MarkedNodes[name][hash] = nil - CurrentPos = hash + for idx,item in ipairs(MarkedNodes[name] or {}) do + if vector.equals(pos, item.pos) then + item.entity:remove() + table.remove(MarkedNodes[name], idx) + CurrentPos = pos + return + end end end local function unmark_all(name) - for _,entity in pairs(MarkedNodes[name] or {}) do - entity:remove() + for _,item in ipairs(MarkedNodes[name] or {}) do + item.entity:remove() end MarkedNodes[name] = nil end @@ -43,12 +63,11 @@ end local function mark_position(name, pos) MarkedNodes[name] = MarkedNodes[name] or {} pos = vector.round(pos) - local hash = minetest.hash_node_position(pos) - if hash ~= CurrentPos then -- entity not punched? + if not CurrentPos or not vector.equals(pos, CurrentPos) then -- entity not punched? local entity = minetest.add_entity(pos, "techage:marker") if entity ~= nil then entity:get_luaentity().player_name = name - MarkedNodes[name][hash] = entity + table.insert(MarkedNodes[name], {pos = pos, entity = entity}) end CurrentPos = nil return true @@ -56,11 +75,10 @@ local function mark_position(name, pos) CurrentPos = nil end -local function table_to_poslist(name) +local function get_poslist(name) local lst = {} - for hash,_ in pairs(MarkedNodes[name] or {}) do - local pos = minetest.get_position_from_hash(hash) - table.insert(lst, pos) + for _,item in ipairs(MarkedNodes[name] or {}) do + table.insert(lst, item.pos) end return lst end @@ -100,21 +118,25 @@ minetest.register_entity(":techage:marker", { local function formspec1(meta) local status = meta:get_string("status") - return "size[8,6.5]".. + return "size[8,7]".. "tabheader[0,0;tab;"..S("Ctrl,Inv")..";1;;true]".. - "button[0.7,0;3,1;record;"..S("Record").."]".. - "button[4.3,0;3,1;ready;"..S("Done").."]".. - "button[0.7,1;3,1;show;"..S("Set").."]".. - "button[4.3,1;3,1;hide;"..S("Remove").."]".. - "label[0.5,2;"..status.."]".. - "list[current_player;main;0,2.8;8,4;]" + "button[0.7,0.5;3,1;record;"..S("Record").."]".. + "button[4.3,0.5;3,1;ready;"..S("Done").."]".. + "button[0.7,1.5;3,1;show;"..S("Set").."]".. + "button[4.3,1.5;3,1;hide;"..S("Remove").."]".. + "label[0.5,2.5;"..status.."]".. + "list[current_player;main;0,3.3;8,4;]" end local function formspec2() - return "size[8,6.5]".. + return "size[8,7]".. "tabheader[0,0;tab;"..S("Ctrl,Inv")..";2;;true]".. - "list[context;main;0,0;8,2;]".. - "list[current_player;main;0,2.8;8,4;]".. + "label[0.3,0.0;1]".. + "label[7.3,0.0;8]".. + "label[0.3,2.4;9]".. + "label[7.3,2.4;16]".. + "list[context;main;0,0.5;8,2;]".. + "list[current_player;main;0,3.3;8,4;]".. "listring[context;main]".. "listring[current_player;main]" end @@ -128,22 +150,22 @@ end local function exchange_node(pos, item, param2) local node = minetest.get_node_or_nil(pos) - local meta = minetest.get_meta(pos) - if node and (not meta or not next((meta:to_table()).fields)) or - minetest.get_item_group(node.name, "techage_door") then - if item and item:get_name() ~= "" and param2 then + if node and is_simple_node(node.name) then + if item and item:get_name() ~= "" then minetest.swap_node(pos, {name = item:get_name(), param2 = param2}) else minetest.remove_node(pos) end if node.name ~= "air" then return ItemStack(node.name), node.param2 + else + return ItemStack(), nil end end - return ItemStack(), nil + return item, param2 end -local function exchange_nodes(pos, nvm) +local function exchange_nodes(pos, nvm, slot) local meta = M(pos) local inv = meta:get_inventory() @@ -153,7 +175,7 @@ local function exchange_nodes(pos, nvm) nvm.pos_list = nvm.pos_list or {} nvm.param2_list = nvm.param2_list or {} - for idx = 1, 16 do + for idx = (slot or 1), (slot or 16) do local pos = nvm.pos_list[idx] if pos and not minetest.is_protected(pos, owner) then item_list[idx], nvm.param2_list[idx] = exchange_node(pos, item_list[idx], nvm.param2_list[idx]) @@ -213,22 +235,18 @@ minetest.register_node("techage:ta3_doorcontroller2", { return elseif fields.record then local inv = meta:get_inventory() - if not inv:is_empty("main") then - meta:set_string("status", S("Error: Inventory already in use")) - else - local nvm = techage.get_nvm(pos) - nvm.pos_list = nil - nvm.is_on = false - meta:set_string("status", S("Recording...")) - local name = player:get_player_name() - minetest.chat_send_player(name, S("Click on all the blocks that are part of the door/gate")) - MarkedNodes[name] = {} - end + local nvm = techage.get_nvm(pos) + nvm.pos_list = nil + nvm.is_on = false + meta:set_string("status", S("Recording...")) + local name = player:get_player_name() + minetest.chat_send_player(name, S("Click on all the blocks that are part of the door/gate")) + MarkedNodes[name] = {} meta:set_string("formspec", formspec1(meta)) elseif fields.ready then local nvm = techage.get_nvm(pos) local name = player:get_player_name() - local pos_list = table_to_poslist(name) + local pos_list = get_poslist(name) local text = #pos_list.." "..S("block positions are stored.") meta:set_string("status", text) nvm.pos_list = pos_list @@ -258,7 +276,7 @@ minetest.register_node("techage:ta3_doorcontroller2", { if minetest.is_protected(pos, player:get_player_name()) then return 0 end - return 0 + return 1 end, allow_metadata_inventory_take = function(pos, listname, index, stack, player) if minetest.is_protected(pos, player:get_player_name()) then @@ -270,10 +288,7 @@ minetest.register_node("techage:ta3_doorcontroller2", { if minetest.is_protected(pos, player:get_player_name()) then return 0 end - - local inv = minetest.get_inventory({type="node", pos=pos}) - local pos_list = minetest.deserialize(M(pos):get_string("pos_list")) or {} - if pos_list[index] and inv:get_stack(listname, index):get_count() == 0 then + if is_simple_node(stack:get_name()) then return 1 end return 0 @@ -301,9 +316,12 @@ minetest.register_node("techage:ta3_doorcontroller2", { techage.register_node({"techage:ta3_doorcontroller2"}, { on_recv_message = function(pos, src, topic, payload) if topic == "on" then - return hide_nodes(pos, nil) + return hide_nodes(pos) elseif topic == "off" then return show_nodes(pos) + elseif topic == "exchange" then + local nvm = techage.get_nvm(pos) + return exchange_nodes(pos, nvm, tonumber(payload)) end return false end, @@ -345,4 +363,4 @@ minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing) mark_position(name, pointed_thing.under) end -end) \ No newline at end of file +end) diff --git a/manuals/manual_ta3_DE.md b/manuals/manual_ta3_DE.md index abfa4ae..f4124e3 100644 --- a/manuals/manual_ta3_DE.md +++ b/manuals/manual_ta3_DE.md @@ -636,10 +636,20 @@ Der Tür Controller dient zur Ansteuerung der TA3 Tür/Tor Blöcke. Beim Tür Co ### TA3 Tür Controller II / Door Controller II -Der Tür Controller II kann alle Arten von Blöcken entfernen und wieder setzen. Um den Tür Controller II anzulernen, muss der "Aufzeichnen" Button gedrückt werden. Dann müssen alle Blöcke angeklickt werden, die Teil der Tür / des Tores sein sollen. Danach muss der "Fertig" Button gedrückt werden. Es können bis zu 16 Blöcke ausgewählt werden. Die entfernten Blöcke werden im Inventar des Controllers gespeichert. Über die Tasten "Entfernen" bzw. "Setzen" kann die Funktion des Controllers von Hand getestet werden. +Der Tür Controller II kann alle Arten von Blöcken entfernen und wieder setzen. Um den Tür Controller II anzulernen, muss der "Aufzeichnen" Button gedrückt werden. Dann müssen alle Blöcke angeklickt werden, die Teil der Tür / des Tores sein sollen. Danach muss der "Fertig" Button gedrückt werden. Es können bis zu 16 Blöcke ausgewählt werden. Die entfernten Blöcke werden im Inventar des Controllers gespeichert. + + Über die Tasten "Entfernen" bzw. "Setzen" kann die Funktion des Controllers von Hand getestet werden. Wird ein `on` / `off` Kommando an den Tür Controller II gesendet, entfernt bzw. setzt er die Blöcke ebenfalls. +Über ein `exchange` Kommando können einzelne Böcke gesetzt, entfernt, bzw. durch andere Blöcke ersetzt werden. Die Slot-Nummer des Inventars (1 .. 16) muss als payload übergeben werden, also: + +``` +$send_cmnd(node_number, "exchange", 2) +``` + +Damit lassen sich auch ausfahrbare Treppen und ähnliches simulieren. + [ta3_doorcontroller|image] ### TA3 Mesecons Umsetzer / TA3 Mesecons Converter diff --git a/manuals/manual_ta3_EN.md b/manuals/manual_ta3_EN.md index 3ee4c73..e59ad5f 100644 --- a/manuals/manual_ta3_EN.md +++ b/manuals/manual_ta3_EN.md @@ -621,7 +621,15 @@ The door controller is used to control the TA3 door/gate blocks. With the door c ### TA3 Door Controller II -The Door Controller II can remove and set all types of blocks. To teach in the Door Controller II, the "Record" button must be pressed. Then all blocks that should be part of the door / gate must be clicked. Then the "Done" button must be pressed. Up to 16 blocks can be selected. The removed blocks are saved in the controller's inventory. The function of the controller can be tested manually using the "Remove" or "Set" buttons. If an `on` /` off` command is sent to the Door Controller II, it removes or sets the blocks as well. +The Door Controller II can remove and set all types of blocks. To teach in the Door Controller II, the "Record" button must be pressed. Then all blocks that should be part of the door / gate must be clicked. Then the "Done" button must be pressed. Up to 16 blocks can be selected. The removed blocks are saved in the controller's inventory. The function of the controller can be tested manually using the "Remove" or "Set" buttons. If an `on` /`off` command is sent to the Door Controller II, it removes or sets the blocks as well. + +Individual blocks can be set, removed or replaced by other blocks via an `exchange` command. The slot number of the inventory (1 .. 16) must be transferred as payload, i.e.: + +``` +$send_cmnd(node_number, "exchange", 2) +``` + +This can also be used to simulate extendable stairs and the like. [ta3_doorcontroller|image] diff --git a/manuals/ta4_lua_controller_EN.md b/manuals/ta4_lua_controller_EN.md index 52a247b..b50b953 100644 --- a/manuals/ta4_lua_controller_EN.md +++ b/manuals/ta4_lua_controller_EN.md @@ -390,6 +390,7 @@ Please note, that this is not a technical distinction, only a logical. | "reset" | nil | Reset the item counter of the TA4 Item Detector block | | "pull" | item string | Start the TA4 pusher to pull/push items.
Example: `default:dirt 8` | | "config" | item string | Configure the TA4 pusher.
Example: `wool:blue` | +| "exchange" | inventory slot number | place/remove/exchange an block by means of the TA3 Door Controller II (techage:ta3_doorcontroller2) | diff --git a/manuals/ta4_lua_controller_EN.pdf b/manuals/ta4_lua_controller_EN.pdf index 0f9e6fd..73fca67 100644 Binary files a/manuals/ta4_lua_controller_EN.pdf and b/manuals/ta4_lua_controller_EN.pdf differ