Michal Cieslakiewicz 372c2f46f2 slprogtools: Tubelib v2 adaptation, minor changes.
Both programmers support new 'func' tab in SaferLua Controller.
Empty data fields are really zero-length now instead of set to "--".

Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
2019-02-03 16:04:16 +01:00

847 lines
27 KiB
Lua

--[[
===============================================
Smartline SaferLua Controller Programming Tools
by Micu (c) 2018
This file contains:
* Memory Copier for SaferLua Controller
* Memory Programmer for SaferLua Controller
Notice: SaferLua Controller uses node formspec
so please switch to 'outp' or 'help' tab for
upload data to all 3 meta strings (must not be
an active tab)
License: LGPLv2.1+
===============================================
]]--
slprogtools = {}
--[[
---------
Variables
---------
]]--
-- default programmer fields
local def_marker = "--@CONF@"
local def_this_var = "THIS"
local def_dev_array = "Machines"
-- colors
local msg_W = minetest.get_color_escape_sequence("#FFFFFF")
local msg_Y = minetest.get_color_escape_sequence("#FFFF00")
local msg_C = minetest.get_color_escape_sequence("#00FFFF")
local msg_M = minetest.get_color_escape_sequence("#FF00FF")
local msg_R = minetest.get_color_escape_sequence("#FFBFBF")
-- help
local help_text = [[SaferLua Controller Memory Programmer
MANUAL
NOTICE: Before accessing SaferLua Controller,
make sure active tab on target controller is
set to either 'outp' or 'help'. Attempt to
write text to active tab silently fails.
This gadget is designed to assist player in
managing SaferLua Controllers and to save
time in deployment and programming of these
useful computers.
Left click on a controller connects to the
computer and displays programmer GUI.
Left click on any Tubelib-compatible machine
stores its number (4-digit unique ID) in
memory. Right click performs quick erase
of this memory area.
Functions (tabs):
* info
Basic information about connected controller.
* memory
Memory Copier mode. Allows to transfer 'init',
'func', 'loop' and 'notes' sections between
device and connected SaferLua Controller.
Checkboxes allow to select on which memory
areas device operates.
* program
Programmer mode. In many scenarios, SaferLua
Controller manages Tubelib machines. This mode
allows to fill a specially marked area in 'init'
section of controller with collected machine
numbers organized in array. It also creates
variable with controller's own number.
Example:
Device has collected 3 machine numbers: 0101,
0202 and 0303. It is connected to controller
0555. Init section looks like below:
-- some code
a = 5
-- default marker below
--@CONF@
-- some other code
b = 0
After pressing Rewrite button, init code of
controller changes to:
-- some code
a = 5
-- default marker below
THIS = "0555"
Machines = Array( "0101", "0202", "0303" )
-- some other code
b = 0
* security
Allows to protect main memory from read or write
operations (or even both)
* help
This window.
]]
--[[
---------------
Sound functions
---------------
]]--
local function play_beep_ok(player_name)
minetest.sound_play("slprogtools_beep_ok", {
to_player = player_name,
gain = 0.8,
})
end
local function play_beep_err(player_name)
minetest.sound_play("slprogtools_beep_err", {
to_player = player_name,
gain = 0.5,
})
end
local function play_click(player_name)
minetest.sound_play("slprogtools_click", {
to_player = player_name,
gain = 0.6,
})
end
--[[
---------------
Device formspec
---------------
]]--
local function formspec_copier(tool, tubelib_id)
-- function requires all metadata to be accessible
-- (or initialized elsewhere)
local tool_def = tool:get_definition()
local desc = tool_def.description
local tool_meta = tool:get_meta()
local init_flag = tool_meta:get_int("init_flag") ~= 0
local func_flag = tool_meta:get_int("func_flag") ~= 0
local loop_flag = tool_meta:get_int("loop_flag") ~= 0
local note_flag = tool_meta:get_int("note_flag") ~= 0
local ro_flag = tool_meta:get_int("ro_flag") ~= 0
local label = tool_meta:get_string("description") or ""
local init_len = string.len(tool_meta:get_string("init_code"))
local func_len = string.len(tool_meta:get_string("func_code"))
local loop_len = string.len(tool_meta:get_string("loop_code"))
local note_len = string.len(tool_meta:get_string("note_text"))
return "size[7,5.25,true]"..
"position[0.5,0.25]" ..
"no_prepend[]" ..
"label[1.5,0;" .. minetest.colorize("#FFFF00", desc) .. "]" ..
"field[0.75,1.25;4.5,0.5;text_label;;" .. label .. "]" ..
"label[0.5,1.75;Connected to controller " .. msg_C ..
tubelib_id .. msg_W .. "]" ..
"checkbox[0.5,2.25;init_flag;include " .. msg_M .. "init()" .. msg_W ..
" code (size: " .. tostring(init_len) .. ");" ..
tostring(init_flag) .. "]" ..
"checkbox[0.5,2.75;func_flag;include " .. msg_M .. "func" .. msg_W ..
" code (size: " .. tostring(func_len) .. ");" ..
tostring(func_flag) .. "]" ..
"checkbox[0.5,3.25;loop_flag;include " .. msg_M .. "loop()" .. msg_W ..
" code (size: " .. tostring(loop_len) .. ");" ..
tostring(loop_flag) .. "]" ..
"checkbox[0.5,3.75;note_flag;include " .. msg_M .. "notes" .. msg_W ..
" text (size: " .. tostring(note_len) .. ");" ..
tostring(note_flag) .. "]" ..
"checkbox[0.5,4.25;ro_flag;read only (archive mode);" ..
tostring(ro_flag) .. "]" ..
"button_exit[5,0.75;1.5,1;label;Label]" ..
"button_exit[5,2;1.5,1;clear;Clear]" ..
"button_exit[5,2.75;1.5,1;download;Download]" ..
"button_exit[5,3.5;1.5,1;upload;Upload]" ..
"button_exit[5,4.25;1.5,1;exit;Exit]"
end
local function formspec_programmer_info(tool, slc_meta)
local slc_id = slc_meta:get_string("number")
local slc_state = tubelib.StateStrings[slc_meta:get_int("state")]
local slc_init_len = string.len(slc_meta:get_string("init"))
local slc_func_len = string.len(slc_meta:get_string("func"))
local slc_loop_len = string.len(slc_meta:get_string("loop"))
local slc_note_len = string.len(slc_meta:get_string("notes"))
return "tabheader[0,1.75;tab;info,memory,program,security,help;1;false;false]" ..
"label[0,1.75;Connected to controller " .. msg_C .. slc_id ..
msg_W .. " (" .. msg_C .. slc_state .. msg_W .. ")]" ..
"label[0,2.5;Code size of " .. msg_M .. "init()" .. msg_W ..
" section is " .. msg_C .. tostring(slc_init_len) .. msg_W ..
" bytes]" ..
"label[0,3;Code size of " .. msg_M .. "func" .. msg_W ..
" section is " .. msg_C .. tostring(slc_func_len) .. msg_W ..
" bytes]" ..
"label[0,3.5;Code size of " .. msg_M .. "loop()" .. msg_W ..
" section is " .. msg_C .. tostring(slc_loop_len) .. msg_W ..
" bytes]" ..
"label[0,4;Text size of " .. msg_M .. "notes" .. msg_W ..
" area is " .. msg_C .. tostring(slc_note_len) .. msg_W ..
" bytes]" ..
"button_exit[5,4.75;1.5,0;exit;Exit]"
end
local function formspec_programmer_mem(tool, slc_meta)
local tool_meta = tool:get_meta()
local init_flag = tool_meta:get_int("init_flag") ~= 0
local func_flag = tool_meta:get_int("func_flag") ~= 0
local loop_flag = tool_meta:get_int("loop_flag") ~= 0
local note_flag = tool_meta:get_int("note_flag") ~= 0
local init_len = string.len(tool_meta:get_string("init_code"))
local func_len = string.len(tool_meta:get_string("func_code"))
local loop_len = string.len(tool_meta:get_string("loop_code"))
local note_len = string.len(tool_meta:get_string("note_text"))
return "tabheader[0,1.75;tab;info,memory,program,security,help;2;false;false]" ..
"checkbox[0,2;init_flag;include " .. msg_M .. "init()" .. msg_W ..
" code (" .. msg_C .. tostring(init_len) .. msg_W ..
" bytes);" .. tostring(init_flag) .. "]" ..
"checkbox[0,2.5;func_flag;include " .. msg_M .. "func" .. msg_W ..
" code (" .. msg_C .. tostring(func_len) .. msg_W ..
" bytes);" .. tostring(func_flag) .. "]" ..
"checkbox[0,3;loop_flag;include " .. msg_M .. "loop()" .. msg_W ..
" code (" .. msg_C .. tostring(loop_len) .. msg_W ..
" bytes);" .. tostring(loop_flag) .. "]" ..
"checkbox[0,3.5;note_flag;include " .. msg_M .. "notes" .. msg_W ..
" text (" .. msg_C .. tostring(note_len) .. msg_W ..
" bytes);" .. tostring(note_flag) .. "]" ..
"button_exit[5,2.25;1.5,0;clear;Clear]" ..
"button_exit[5,3;1.5,0;download;Download]" ..
"button_exit[5,3.75;1.5,0;upload;Upload]" ..
"button_exit[5,4.75;1.5,0;exit;Exit]"
end
local function formspec_programmer_prog(tool, slc_meta)
local tool_meta = tool:get_meta()
local prog_mark = tool_meta:get_string("prog_mark")
local this_var = tool_meta:get_string("this_var")
local dev_array = tool_meta:get_string("dev_array")
local numlist = minetest.deserialize(
tool_meta:get_string("number_list"))
return "tabheader[0,1.75;tab;info,memory,program,security,help;3;false;false]" ..
"label[0,1.75;Machine numbers in memory: " .. msg_C ..
tostring(#numlist) .. msg_W .. "]" ..
"label[0,2.75;Substitution marker in init()]" ..
"field[3.4,3.3;1.75,0;marker_text;;" .. prog_mark .. "]" ..
"field_close_on_enter[marker_text;false]" ..
"label[0,3.5;Controller number variable]" ..
"field[3.4,4.05;1.75,0;slc_var;;" .. this_var .. "]" ..
"field_close_on_enter[slc_var;false]" ..
"label[0,4.25;Machine numbers array]" ..
"field[3.4,4.8;1.75,0;dev_array;;" .. dev_array .. "]" ..
"field_close_on_enter[dev_array;false]" ..
"button_exit[5,2.5;1.5,0;erase;Erase]" ..
"button_exit[5,3.25;1.5,0;rewrite;Rewrite]" ..
"button_exit[5,4.75;1.5,0;exit;Exit]"
end
local function formspec_programmer_sec(tool, slc_meta)
local tool_meta = tool:get_meta()
local ro_flag = tool_meta:get_int("ro_flag") ~= 0
local wo_flag = tool_meta:get_int("wo_flag") ~= 0
return "tabheader[0,1.75;tab;info,memory,program,security,help;4;false;false]" ..
"checkbox[0.5,2;ro_flag;write protection (disable download and clear);" ..
tostring(ro_flag) .. "]" ..
"checkbox[0.5,2.5;wo_flag;read protection (disable upload);" ..
tostring(wo_flag) .. "]" ..
"button_exit[5,4.75;1.5,0;exit;Exit]"
end
local function formspec_programmer_help(tool, slc_meta)
return "tabheader[0,1.75;tab;info,memory,program,security,help;5;false;false]" ..
"textarea[0.25,1.75;7,2.75;help;;" .. help_text .. "]" ..
"button_exit[5,4.75;1.5,0;exit;Exit]"
end
local function formspec_programmer(tool, slc_meta, tab_idx)
-- function requires all metadata to be accessible
-- (or initialized elsewhere)
local tool_def = tool:get_definition()
local label = tool_def.description
local formspec_header = "size[7,5.25,true]" ..
"position[0.5,0.25]" .. "no_prepend[]" ..
"label[1.25,0;" .. minetest.colorize("#FFFF00", label) .. "]"
if not tab_idx or tab_idx == 1 then
-- info
return formspec_header ..
formspec_programmer_info(tool, slc_meta)
elseif tab_idx == 2 then
-- memory
return formspec_header ..
formspec_programmer_mem(tool, slc_meta)
elseif tab_idx == 3 then
-- program
return formspec_header ..
formspec_programmer_prog(tool, slc_meta)
elseif tab_idx == 4 then
-- security
return formspec_header ..
formspec_programmer_sec(tool, slc_meta)
elseif tab_idx == 5 then
-- help
return formspec_header ..
formspec_programmer_help(tool, slc_meta)
end
end
--[[
---------------
Device metadata
---------------
]]--
local function init_metadata_copier(player, tool)
-- write correct metadata only if not present
local tool_meta = tool:get_meta()
local tool_upd = false
local metatable = tool_meta:to_table()
if not metatable.fields["ro_flag"] then
tool_meta:set_int("ro_flag", 0)
tool_upd = true
end
if not metatable.fields["init_flag"] then
tool_meta:set_int("init_flag", 1)
tool_upd = true
end
if not metatable.fields["func_flag"] then
tool_meta:set_int("func_flag", 1)
tool_upd = true
end
if not metatable.fields["loop_flag"] then
tool_meta:set_int("loop_flag", 1)
tool_upd = true
end
if not metatable.fields["note_flag"] then
tool_meta:set_int("note_flag", 1)
tool_upd = true
end
if not metatable.fields["init_code"] then
tool_meta:set_string("init_code", "")
tool_upd = true
end
if not metatable.fields["func_code"] then
tool_meta:set_string("func_code", "")
tool_upd = true
end
if not metatable.fields["loop_code"] then
tool_meta:set_string("loop_code", "")
tool_upd = true
end
if not metatable.fields["note_text"] then
tool_meta:set_string("note_text", "")
tool_upd = true
end
-- all done
if tool_upd then player:set_wielded_item(tool) end
return tool_upd
end
local function init_metadata_programmer(player, tool)
-- write correct metadata only if not present
local tool_meta = tool:get_meta()
local tool_upd = false
local metatable = tool_meta:to_table()
if not metatable.fields["wo_flag"] then
tool_meta:set_int("wo_flag", 0)
tool_upd = true
end
if not metatable.fields["prog_mark"] then
tool_meta:set_string("prog_mark", def_marker)
tool_upd = true
end
if not metatable.fields["this_var"] then
tool_meta:set_string("this_var", def_this_var)
tool_upd = true
end
if not metatable.fields["dev_array"] then
tool_meta:set_string("dev_array", def_dev_array)
tool_upd = true
end
if not metatable.fields["number_list"] then
tool_meta:set_string("number_list", minetest.serialize({}))
tool_upd = true
end
if tool_upd then player:set_wielded_item(tool) end
-- copier metadata is part of device
return init_metadata_copier(player, tool) or tool_upd
end
--[[
-----------
Main Window
-----------
]]--
-- formspec callback
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "slprogtools:slc_memory_copier" and
formname ~= "slprogtools:slc_memory_programmer" then
return false
end
if not fields then return true end
local player_name = player:get_player_name()
local tool = player:get_wielded_item()
local tool_def = tool:get_definition()
local label = tool_def._label
local tool_meta = tool:get_meta()
local slc_pos = minetest.deserialize(
tool_meta:get_string("lua_pos"))
local slc_meta = minetest.get_meta(slc_pos)
local slc_id = slc_meta:get_string("number")
local tool_upd = false
local play_snd = true
if fields.tab then
minetest.show_formspec(player_name, tool_def.name,
tool_def._formspec(tool, slc_meta, tonumber(fields.tab)))
return true
end
if fields.clear or fields.download or fields.upload
or fields.erase or fields.rewrite
or fields.label or fields.key_enter_field
or fields.exit or fields.quit then
play_snd = false
end
if fields.init_flag then
tool_meta:set_int("init_flag", fields.init_flag == "true" and 1 or 0)
if play_snd then play_click(player_name) end
tool_upd = true
end
if fields.func_flag then
tool_meta:set_int("func_flag", fields.func_flag == "true" and 1 or 0)
if play_snd then play_click(player_name) end
tool_upd = true
end
if fields.loop_flag then
tool_meta:set_int("loop_flag", fields.loop_flag == "true" and 1 or 0)
if play_snd then play_click(player_name) end
tool_upd = true
end
if fields.note_flag then
tool_meta:set_int("note_flag", fields.note_flag == "true" and 1 or 0)
if play_snd then play_click(player_name) end
tool_upd = true
end
if fields.ro_flag then
tool_meta:set_int("ro_flag", fields.ro_flag == "true" and 1 or 0)
if play_snd then play_click(player_name) end
tool_upd = true
end
if fields.wo_flag then
tool_meta:set_int("wo_flag", fields.wo_flag == "true" and 1 or 0)
if play_snd then play_click(player_name) end
tool_upd = true
end
if fields.marker_text then
local prog_mark = fields.marker_text:trim()
if prog_mark == "" then prog_mark = def_marker end
tool_meta:set_string("prog_mark", prog_mark)
if play_snd then play_click(player_name) end
tool_upd = true
end
if fields.slc_var then
local this_var = fields.slc_var:trim()
if this_var == "" then this_var = def_this_var end
tool_meta:set_string("this_var", this_var)
if play_snd then play_click(player_name) end
tool_upd = true
end
if fields.dev_array then
local dev_array = fields.dev_array:trim()
if dev_array == "" then dev_array = def_dev_array end
tool_meta:set_string("dev_array", dev_array)
if play_snd then play_click(player_name) end
tool_upd = true
end
if tool_upd then
player:set_wielded_item(tool) -- update data for buttons
tool_upd = false
end
if fields.clear or fields.download or fields.upload then
-- copier window or memory tab buttons
-- (this must work also for copier which has no WO flag)
local ro_flag = tool_meta:get_int("ro_flag") == 1
local wo_flag = tool_meta:get_int("wo_flag") == 1
if (fields.clear or fields.download) and ro_flag then
play_beep_err(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " .. msg_R ..
"Device memory is write-protected!")
return true
elseif fields.upload and wo_flag then
play_beep_err(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " .. msg_R ..
"Device memory is read-protected!")
return true
end
local init_flag = tool_meta:get_int("init_flag") ~= 0
local func_flag = tool_meta:get_int("func_flag") ~= 0
local loop_flag = tool_meta:get_int("loop_flag") ~= 0
local note_flag = tool_meta:get_int("note_flag") ~= 0
local clr_list = {}
if fields.clear then
if init_flag then
tool_meta:set_string("init_code", "")
clr_list[#clr_list + 1] = "init"
tool_upd = true
end
if func_flag then
tool_meta:set_string("func_code", "")
clr_list[#clr_list + 1] = "func"
tool_upd = true
end
if loop_flag then
tool_meta:set_string("loop_code", "")
clr_list[#clr_list + 1] = "loop"
tool_upd = true
end
if note_flag then
tool_meta:set_string("note_text", "")
clr_list[#clr_list + 1] = "notes"
tool_upd = true
end
play_click(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " .. msg_W ..
"Memory cleared (" ..
table.concat(clr_list, ", ") .. ")")
elseif fields.download then
local init_len, func_len, loop_len, note_len = -1, -1, -1, -1
if init_flag then
tool_meta:set_string("init_code",
slc_meta:get_string("init"))
init_len = string.len(
tool_meta:get_string("init_code"))
tool_upd = true
end
if func_flag then
tool_meta:set_string("func_code",
slc_meta:get_string("func"))
func_len = string.len(
tool_meta:get_string("func_code"))
tool_upd = true
end
if loop_flag then
tool_meta:set_string("loop_code",
slc_meta:get_string("loop"))
loop_len = string.len(
tool_meta:get_string("loop_code"))
tool_upd = true
end
if note_flag then
tool_meta:set_string("note_text",
slc_meta:get_string("notes"))
note_len = string.len(
tool_meta:get_string("note_text"))
tool_upd = true
end
play_beep_ok(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " .. msg_W ..
"Download from " .. msg_C .. slc_id .. msg_W ..
" completed (init " .. msg_C ..
(init_len < 0 and "skipped" or tostring(init_len) ..
msg_W .. " bytes") .. msg_W .. ", func " .. msg_C ..
(func_len < 0 and "skipped" or tostring(func_len) ..
msg_W .. " bytes") .. msg_W .. ", loop " .. msg_C ..
(loop_len < 0 and "skipped" or tostring(loop_len) ..
msg_W .. " bytes") .. msg_W .. ", notes " .. msg_C ..
(note_len < 0 and "skipped" or tostring(note_len) ..
msg_W .. " bytes)"))
elseif fields.upload then
local init_len, func_len, loop_len, note_len = -1, -1, -1, -1
if slc_meta:get_int("state") ~= tubelib.STOPPED then
play_beep_err(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " .. msg_R ..
"Cannot upload to running system!")
return true
end
if init_flag then
slc_meta:set_string("init",
tool_meta:get_string("init_code"))
init_len = string.len(
slc_meta:get_string("init"))
end
if func_flag then
slc_meta:set_string("func",
tool_meta:get_string("func_code"))
func_len = string.len(
slc_meta:get_string("func"))
end
if loop_flag then
slc_meta:set_string("loop",
tool_meta:get_string("loop_code"))
loop_len = string.len(
slc_meta:get_string("loop"))
end
if note_flag then
slc_meta:set_string("notes",
tool_meta:get_string("note_text"))
note_len = string.len(
slc_meta:get_string("notes"))
end
play_beep_ok(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " .. msg_W ..
"Upload to " .. msg_C .. slc_id .. msg_W ..
" completed (init " .. msg_C ..
(init_len < 0 and "skipped" or tostring(init_len) ..
msg_W .. " bytes") .. msg_W .. ", func " .. msg_C ..
(func_len < 0 and "skipped" or tostring(func_len) ..
msg_W .. " bytes") .. msg_W .. ", loop " .. msg_C ..
(loop_len < 0 and "skipped" or tostring(loop_len) ..
msg_W .. " bytes") .. msg_W .. ", notes " .. msg_C ..
(note_len < 0 and "skipped" or tostring(note_len) ..
msg_W .. " bytes)"))
end
elseif fields.erase or fields.rewrite then
-- programmer tab buttons
if fields.erase then
tool_meta:set_string("number_list",
minetest.serialize({}))
tool_upd = true
play_click(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " .. msg_W ..
"All machine numbers erased from memory")
elseif fields.rewrite then
if slc_meta:get_int("state") ~= tubelib.STOPPED then
play_beep_err(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " .. msg_R ..
"Cannot rewrite code of running system!")
return true
end
local prog_mark = tool_meta:get_string("prog_mark")
local this_var = tool_meta:get_string("this_var")
local dev_array = tool_meta:get_string("dev_array")
local newcode = this_var .. " = \"" ..
slc_id .. "\"\n" ..dev_array .. " = Array( "
local numlist = minetest.deserialize(
tool_meta:get_string("number_list"))
for i, n in ipairs(numlist) do
newcode = newcode .. "\"" .. n .. "\""
if i < #numlist then
newcode = newcode .. ", "
end
end
newcode = newcode .. " )"
local init = slc_meta:get_string("init")
local newinit, replnum = string.gsub(init, prog_mark,
newcode, 1)
slc_meta:set_string("init", newinit)
if replnum > 0 then
play_beep_ok(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " ..
msg_W .. "Machine numbers injected into " ..
msg_C .. slc_id .. msg_W .. " init code")
else
play_beep_err(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " .. msg_R ..
"No marker in code for machine numbers")
return true
end
end
elseif fields.label or fields.key_enter_field == "text_label" then
-- copier label
local new_txtlbl = fields.text_label:trim()
tool_meta:set_string("description", new_txtlbl)
play_click(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " ..
msg_W .. "Text label " ..
(new_txtlbl == "" and "reset" or "set"))
tool_upd = true
elseif fields.exit or fields.quit then
play_click(player_name)
end
if tool_upd then player:set_wielded_item(tool) end
return true
end)
-- show formspec
local function show_menu_copier(item, player, pointed_thing)
if pointed_thing.type ~= "node" then return nil end
local player_name = player:get_player_name()
local tool_def = item:get_definition()
local label = tool_def._label
if minetest.get_node(pointed_thing.under).name ~=
"sl_controller:controller" then
play_beep_err(player_name)
return nil
end
local slc_meta = minetest.get_meta(pointed_thing.under)
if slc_meta:get_string("owner") ~= player_name then
play_beep_err(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " ..
msg_R .. "Access denied - not owner!")
return nil
end
tool_def._init_metadata(player, item)
local tool_meta = item:get_meta()
tool_meta:set_string("lua_pos", -- for event function to get meta
minetest.serialize(pointed_thing.under))
player:set_wielded_item(item)
local tubelib_id = slc_meta:get_string("number")
play_beep_ok(player_name)
minetest.show_formspec(player_name, tool_def.name,
tool_def._formspec(item, tubelib_id))
return item -- we change metadata so on_use must receive updated item
end
local function on_use_programmer(item, player, pointed_thing)
if pointed_thing.type ~= "node" then return nil end
local player_name = player:get_player_name()
local tool_def = item:get_definition()
local label = tool_def._label
local pt_id = tubelib.get_node_number(pointed_thing.under)
if not pt_id then
play_beep_err(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " ..
msg_R .. "Incompatible logic - unable to read ID!")
return nil
end
local pt_meta = minetest.get_meta(pointed_thing.under)
local owner = pt_meta:get_string("owner") or ""
if owner ~= "" and owner ~= player_name then
play_beep_err(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " ..
msg_R .. "Access denied - not owner!")
return nil
end
tool_def._init_metadata(player, item)
local tool_meta = item:get_meta()
if minetest.get_node(pointed_thing.under).name ==
"sl_controller:controller" then
-- pointing at SaferLua Controller
tool_meta:set_string("lua_pos", -- for event function
minetest.serialize(pointed_thing.under))
player:set_wielded_item(item)
play_beep_ok(player_name)
minetest.show_formspec(player_name, tool_def.name,
tool_def._formspec(item, pt_meta, 1))
else
-- pointing at Techpack device
local numlist = minetest.deserialize(
tool_meta:get_string("number_list"))
numlist[#numlist + 1] = pt_id
tool_meta:set_string("number_list", minetest.serialize(numlist))
play_beep_ok(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " .. msg_W ..
"Machine with number " .. msg_C .. pt_id ..
msg_W .. " stored at position " .. msg_M ..
tostring(#numlist))
end
return item -- we change metadata so on_use must receive updated item
end
--[[
-----------------
Tool registration
-----------------
]]--
minetest.register_tool("slprogtools:slc_memory_copier", {
description = "SaferLua Controller Memory Copier",
wield_image = "slprogtools_memory_copier_hand.png",
wield_scale = { x = 1, y = 1, z = 1 },
inventory_image = "slprogtools_memory_copier_inv.png",
stack_max = 1,
range = 4,
_label = "SLCMemoryCopier",
_init_metadata = init_metadata_copier,
_formspec = formspec_copier,
on_use = show_menu_copier,
})
minetest.register_tool("slprogtools:slc_memory_programmer", {
description = "SaferLua Controller Memory Programmer",
wield_image = "slprogtools_memory_programmer_hand.png",
wield_scale = { x = 1, y = 1, z = 1 },
inventory_image = "slprogtools_memory_programmer_inv.png",
stack_max = 1,
range = 4,
_label = "SLCMemoryProgrammer",
_init_metadata = init_metadata_programmer,
_formspec = formspec_programmer,
on_use = on_use_programmer,
on_secondary_use = function(item, user, pointed_thing)
-- quick erase machine codes
local player_name = user:get_player_name()
local label = item:get_definition()._label
local tool_meta = item:get_meta()
tool_meta:set_string("number_list",
minetest.serialize({}))
play_click(player_name)
minetest.chat_send_player(player_name,
msg_Y .. "[" .. label .. "] " .. msg_W ..
"All machine numbers erased from memory")
return item
end
})
--[[
--------
Crafting
--------
]]--
local metal_comp = "default:gold_ingot"
if minetest.get_modpath("moreores") and moreores then
metal_comp = "moreores:silver_ingot"
end
minetest.register_craft({
output = "slprogtools:slc_memory_copier",
type = "shaped",
recipe = {
{ "", "default:steel_ingot", "" },
{ metal_comp, "tubelib:wlanchip", "default:copper_ingot" },
{ "", "dye:blue", "" },
},
})
minetest.register_craft({
output = "slprogtools:slc_memory_programmer",
type = "shapeless",
recipe = { "slprogtools:slc_memory_copier", "default:mese_crystal", "tubelib_addons2:programmer" },
})