wireless_touchscreens/init.lua

196 lines
6.1 KiB
Lua

--
-- Minetest wireless touchscreens mod
--
wireless_touchscreens = {}
local storage = minetest.get_mod_storage()
-- Node protection checking, copied from scriptblocks.
if minetest.get_modpath('scriptblocks') then
wireless_touchscreens.check_protection = scriptblocks.check_protection
else
wireless_touchscreens.check_protection = function(pos, name)
if type(name) ~= 'string' then
name = name:get_player_name()
end
if minetest.is_protected(pos, name) and
not minetest.check_player_privs(name, {protection_bypass=true}) then
minetest.record_protection_violation(pos, name)
return true
end
return false
end
end
-- Allowed touchscreens
wireless_touchscreens.parents = {}
wireless_touchscreens.screens = {}
-- Override formspec updates
wireless_touchscreens.update_ts_formspec = digistuff.update_ts_formspec
digistuff.update_ts_formspec = function(pos, ...)
wireless_touchscreens.update_ts_formspec(pos, ...)
local spos = minetest.pos_to_string(pos)
local nodes = storage:get_string(spos)
if not nodes or #nodes < 5 then
return
end
local save = false
local any = false
nodes = minetest.deserialize(nodes)
local formspec = minetest.get_meta(pos):get_string('formspec')
-- Update the nodes
for node, _ in pairs(nodes) do
any = true
local remote = minetest.string_to_pos(node)
local name = minetest.get_node(remote).name
if _ and wireless_touchscreens.screens[name] then
local meta = minetest.get_meta(remote)
local owner, r = meta:get_string('owner'), meta:get_string('remote')
if r ~= spos or
wireless_touchscreens.check_protection(remote, owner) then
wireless_touchscreens.on_construct(remote)
nodes[node] = nil
save = true
else
meta:set_string('formspec', formspec)
end
elseif name ~= 'ignore' then
nodes[node] = nil
save = true
end
end
if not any then
storage:set_string(spos, '')
elseif save then
storage:set_string(spos, minetest.serialize(nodes))
end
end
-- Node handlers
wireless_touchscreens.on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string('formspec', 'field[remote;Remote touchscreen position;]')
meta:set_string('owner', '')
meta:set_string('remote', '')
end
wireless_touchscreens.on_receive_fields = function(pos,formname,fields,sender)
local victim = sender:get_player_name()
local meta = minetest.get_meta(pos)
local remote = meta:get_string('remote')
local owner = meta:get_string('owner')
if remote then remote = minetest.string_to_pos(remote) end
-- Forward fields onto digistuff if the touchscreen protection hasn't
-- changed
if remote and owner then
local name = minetest.get_node(remote).name
if minetest.is_protected(remote, owner) or not
wireless_touchscreens.parents[name] then
storage:set_string(minetest.pos_to_string(remote), '')
-- TODO: Make this close_formspec more specific.
minetest.close_formspec(victim, '')
if name ~= 'ignore' then
minetest.chat_send_player(victim,
'The remote touchscreen is no longer accessible!')
wireless_touchscreens.on_construct(pos)
else
minetest.chat_send_player(victim,
'The remote touchscreen is not loaded!')
end
else
digistuff.ts_on_receive_fields(remote, formname, fields, sender)
end
return
elseif wireless_touchscreens.check_protection(pos, victim) or
not fields.remote then
return
end
remote = minetest.string_to_pos(fields.remote)
if not remote then
return minetest.chat_send_player(victim, 'Invalid position!')
end
local name = minetest.get_node(remote).name
if wireless_touchscreens.check_protection(remote, victim) then
return
elseif not wireless_touchscreens.parents[name] then
minetest.chat_send_player(victim, 'That block is not a touchscreen!')
return
end
local sremote = minetest.pos_to_string(remote)
meta:set_string('remote', sremote)
meta:set_string('owner', victim)
-- Add the touchscreen to the list to update
local data = storage:get_string(sremote)
if data and #data > 5 then
data = minetest.deserialize(data)
else
data = {}
end
data[minetest.pos_to_string(pos)] = true
storage:set_string(sremote, minetest.serialize(data))
-- Make the remote touchscreen updated.
meta:set_string('formspec',
minetest.get_meta(remote):get_string('formspec'))
minetest.chat_send_player(victim, 'Remote touchscreen set!')
end
-- Register a wireless node
wireless_touchscreens.register_node = function(name, parent, texture_overlay)
local def2 = minetest.registered_nodes[parent]
if not def2 then error('Node ' .. parent .. ' does not exist!') end
local def = {}
for key, value in pairs(def2) do
def[key] = value
end
def.name = nil
def.digiline = nil
def.description = 'Wireless ' .. def.description
def.on_construct = wireless_touchscreens.on_construct
def.on_receive_fields = wireless_touchscreens.on_receive_fields
texture_overlay = texture_overlay or '^[colorize:#24f2'
wireless_touchscreens.parents[parent] = true
wireless_touchscreens.screens[name] = true
for n, tile in ipairs(def.tiles) do
def.tiles[n] = tile .. texture_overlay
end
minetest.register_node(name, def)
end
-- Create the node
wireless_touchscreens.register_node('wireless_touchscreens:ts',
'digistuff:touchscreen')
minetest.register_craft({
output = 'wireless_touchscreens:ts',
type = 'shapeless',
recipe = {
'digistuff:touchscreen',
minetest.get_modpath('pipeworks') and 'pipeworks:teleport_tube_1'
or 'default:mese',
'default:diamond'
}
})