281 lines
7.4 KiB
Lua
281 lines
7.4 KiB
Lua
|
|
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")
|