local unpack = table.unpack or unpack local formspec_elements = dofile(minetest.get_modpath("digistuff").."/formspec_elements.lua") local formspec_version = 6 local function create_element_string(element, values) if type(element) == "function" then return element(values) end local new_values = {} for i,name in ipairs(element[2]) do local value = element[4][i](values[name], element[3][i]) table.insert(new_values, value) end return string.format(element[1], unpack(new_values)) end local function modify_element_string(old, values) local e = string.match(old, "^(.-)%[") local element = formspec_elements[e] if type(element) == "function" then return old -- No-op for special elements, as there is no format string end local old_values = {string.match(old, element[5])} local new_values = {} for i,name in ipairs(element[2]) do local value = element[4][i](values[name], old_values[i] or element[3][i]) table.insert(new_values, value) end return string.format(element[1], unpack(new_values)) end local function check_old_command(msg) local cmd = msg.command if cmd == "lock" then return {command = "set", locked = true} end if cmd == "unlock" then return {command = "set", locked = false} end if cmd == "realcoordinates" then return {command = "set", real_coordinates = msg.enabled} end if string.match(cmd, "^add%a+") then msg.element = string.sub(cmd, 4) msg.command = "add" if msg.image then -- Compatibility for old name msg.texture_name = msg.image end end return msg end local function process_command(meta, data, msg) msg = check_old_command(msg) local cmd = msg.command if cmd == "clear" then data = {} elseif cmd == "add" then local element = formspec_elements[msg.element] if element then local str = create_element_string(element, msg) table.insert(data, str) end elseif cmd == "insert" then local element = formspec_elements[msg.element] local index = tonumber(msg.index) if element and index and index > 0 then local str = create_element_string(element, msg) table.insert(data, index, str) end elseif cmd == "replace" then local element = formspec_elements[msg.element] local index = tonumber(msg.index) if element and index and data[index] then local str = create_element_string(element, msg) data[index] = str end elseif cmd == "modify" then local index = tonumber(msg.index) if index and data[index] then local str = modify_element_string(data[index], msg) data[index] = str end elseif cmd == "remove" then local index = tonumber(msg.index) if index and data[index] then table.remove(data, index) end elseif cmd == "delete" then local index = tonumber(msg.index) if index and data[index] then data[index] = nil end elseif cmd == "set" then if msg.locked ~= nil then meta:set_int("locked", msg.locked == false and 0 or 1) end if msg.no_prepend ~= nil then meta:set_int("no_prepend", msg.no_prepend == false and 0 or 1) end if msg.real_coordinates ~= nil then meta:set_int("real_coordinates", msg.real_coordinates == false and 0 or 1) end if msg.fixed_size ~= nil then meta:set_int("fixed_size", msg.fixed_size == false and 0 or 1) end if type(msg.width) == "number" then local value = math.max(1, math.min(100, msg.width)) meta:set_string("width", string.format("%.4g", value)) end if type(msg.height) == "number" then local value = math.max(1, math.min(100, msg.height)) meta:set_string("height", string.format("%.4g", value)) end if type(msg.focus) == "string" then meta:set_string("focus", minetest.formspec_escape(msg.focus)) end end return data end local function get_data(meta) local data = minetest.deserialize(meta:get("data")) if data and type(data[1]) == "table" then -- Old data, convert to new format for i,v in ipairs(data) do local element = formspec_elements[v.type] data[i] = create_element_string(element, v) end end return data end local function create_formspec(meta, data) local fs = "formspec_version["..formspec_version.."]" local width = tonumber(meta:get_string("width")) or 10 local height = tonumber(meta:get_string("height")) or 8 if meta:get_int("fixed_size") == 1 then fs = fs.."size["..width..","..height..",true]" else fs = fs.."size["..width..","..height.."]" end if meta:get_int("no_prepend") == 1 then fs = fs.."no_prepend[]" end if not meta:get("real_coordinates") and not meta:get("realcoordinates") then fs = fs.."real_coordinates[false]" end local focus = meta:get("focus") if focus then fs = fs.."set_focus["..focus.."]" end local data_size = 0 for i in pairs(data) do if i > data_size then data_size = i end end for i=1, data_size do if data[i] then fs = fs..data[i] end end return fs end local function update_formspec(pos, meta, data) data = data or get_data(meta) if not meta:get("init") then meta:set_string("formspec", "field[channel;Channel;]") elseif not data then meta:set_string("formspec", "size[10,8]") else meta:set_string("formspec", create_formspec(meta, data)) end end local function on_digiline(pos, node, channel, msg) if type(msg) ~= "table" then return end local meta = minetest.get_meta(pos) if channel ~= meta:get_string("channel") then return end local data = get_data(meta) or {} if type(msg.command) == "string" then data = process_command(meta, data, msg) else for _,v in ipairs(msg) do if type(v) == "table" and type(v.command) == "string" then data = process_command(meta, data, v) end end end meta:set_string("data", minetest.serialize(data)) update_formspec(pos, meta, data) end local function on_receive_fields(pos, _, fields, player) local meta = minetest.get_meta(pos) local name = player:get_player_name() if meta:get_int("locked") == 1 and minetest.is_protected(pos, name) then minetest.chat_send_player(name, "You are not authorized to use this screen.") return end if not meta:get("init") and fields.channel then meta:set_string("channel", fields.channel) meta:set_int("init", 1) update_formspec(pos, meta) else local channel = meta:get_string("channel") fields.clicker = name digilines.receptor_send(pos, digilines.rules.default, channel, fields) end end minetest.register_node("digistuff:touchscreen", { description = "Digilines Touchscreen", groups = {cracky = 3}, is_ground_content = false, tiles = { "digistuff_panel_back.png", "digistuff_panel_back.png", "digistuff_panel_back.png", "digistuff_panel_back.png", "digistuff_panel_back.png", "digistuff_ts_front.png" }, drawtype = "nodebox", paramtype = "light", paramtype2 = "facedir", node_box = { type = "fixed", fixed = { {-0.5, -0.5, 0.4, 0.5, 0.5, 0.5} } }, on_construct = function(pos) local meta = minetest.get_meta(pos) update_formspec(pos, meta) end, on_receive_fields = on_receive_fields, digilines = { receptor = {}, effector = { action = on_digiline } }, _digistuff_channelcopier_fieldname = "channel", _digistuff_channelcopier_onset = function(pos) local meta = minetest.get_meta(pos) meta:set_int("init", 1) update_formspec(pos, meta) end, }) minetest.register_craft({ output = "digistuff:touchscreen", recipe = { {"mesecons_luacontroller:luacontroller0000", "default:glass", "default:glass"}, {"default:glass", "digilines:lcd", "default:glass"}, {"default:glass", "default:glass", "default:glass"} } }) minetest.register_alias("digistuff:advtouchscreen", "digistuff:touchscreen")