digiline_memory/memory.lua

63 lines
1.5 KiB
Lua

-- © 2017 numberZero
local ROW_SIZE_LIMIT = 4 * 1024
local MSG_INVALID_ADDRESS = "Invalid address"
local MSG_DATA_TOO_LONG = "Data too long"
local function get_meta_field_name(addr, desc)
if type(addr) ~= "number" then
return false
end
local int, frac = math.modf(addr)
if frac ~= 0 or int < 0 or int >= desc.size then
return false
end
return true, "data_"..int
end
function digiline_memory.on_digiline_receive(pos, node, channel, msg)
if type(msg) ~= "table" or not msg.cmd then
return
end
local meta = minetest.get_meta(pos)
if channel ~= meta:get_string("channel") then
return
end
local ok = false
local addr
local value
local desc = minetest.registered_nodes[minetest.get_node(pos).name].digiline_memory
if msg.cmd == "get" then
ok, addr = get_meta_field_name(msg.addr, desc)
if ok then
value = minetest.deserialize(meta:get_string(addr))
else
value = MSG_INVALID_ADDRESS
end
elseif msg.cmd == "set" then
ok, addr = get_meta_field_name(msg.addr, desc)
if ok then
if msg.value == nil then
value = ""
else
value = minetest.serialize(msg.value)
end
if #value > ROW_SIZE_LIMIT then
ok = false
value = MSG_DATA_TOO_LONG
else
meta:set_string(addr, value)
meta:mark_as_private(addr)
value = nil -- don't send it back
end
else
value = MSG_INVALID_ADDRESS
end
elseif msg.cmd == "clear" then
if desc.reset then
ok = desc:reset(pos) ~= false
end
end
digiline:receptor_send(pos, digiline.rules.default, channel, {ok=ok, value=value})
end