commit c5ce15e145e67c844e2b10888dbac8469f0c41fd Author: luk3yx Date: Sun Nov 4 16:40:26 2018 +1300 Initial commit diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..b274816 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +*Copyright © 2018 by luk3yx* + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..34925c6 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# Wireless touchscreens + +A Minetest mod that adds wireless digistuff touchscreens, inspired by +[digitouch]. + +[digitouch]: https://gitlab.com/rdococ/digitouch + +## Crafting + +To craft a wireless touchscreen, use a regular touchscreen, a teleportation tube +(mese block if pipeworks isn't installed) and a diamond. + +## Dependencies + +This mod depends on `digistuff` and `digilines`. + +The following optional dependencies may exist: + - `default`: Crafting recipes. + - `pipeworks`: Optional crafting recipe change. + - `scriptblocks`: Not required at all, however when `scriptblocks` is loaded + this mod will use a scriptblocks API function instead of its own to + save memory. diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..705ce9b --- /dev/null +++ b/depends.txt @@ -0,0 +1,5 @@ +digilines +digistuff +scriptblocks? +pipeworks? +default? diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..b6ecedb --- /dev/null +++ b/init.lua @@ -0,0 +1,192 @@ +-- +-- 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 + end + end + + if not any then + minetest.forceload_free_block(remote, true) + 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 + minetest.forceload_block(remote, true) + if minetest.is_protected(remote, owner) or not + wireless_touchscreens.parents[minetest.get_node(remote).name] + then + minetest.forceload_free_block(remote, true) + storage:set_string(minetest.pos_to_string(remote), '') + -- TODO: Make this close_formspec more specific. + minetest.close_formspec(victim, '') + minetest.chat_send_player(victim, + 'The remote touchscreen is no longer accessible!') + wireless_touchscreens.on_construct(pos) + 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 + + minetest.forceload_block(remote, true) + + local name = minetest.get_node(remote).name + if wireless_touchscreens.check_protection(remote, victim) then + return minetest.forceload_free_block(remote, true) + elseif not wireless_touchscreens.parents[name] then + minetest.chat_send_player(victim, 'That block is not a touchscreen!') + return minetest.forceload_free_block(remote, true) + 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' + } +})