turtle/floppy.lua

163 lines
5.3 KiB
Lua
Raw Permalink Normal View History

floppy = {}
local floppies = db.read_file("floppies")
minetest.register_on_shutdown(function()
db.write_file("floppies", floppies)
end)
local function create_floppy_id()
return #floppies + 1
end
local function handle_floppy_meta(stack)
if stack.metadata == "" or stack.metadata == nil then
local id = create_floppy_id()
stack.metadata = tostring(id)
floppies[id] = string.rep(string.char(0), 16384)
return floppies[id], true
elseif string.len(stack.metadata) >= 1000 then
local id = create_floppy_id()
floppies[id] = stack.metadata
stack.metadata = tostring(id)
return floppies[id], true
else
if floppies[tonumber(stack.metadata)] == nil then
floppies[tonumber(stack.metadata)] = string.rep(string.char(0), 16384)
end
return floppies[tonumber(stack.metadata)], false
end
end
local function set_floppy_contents(name, contents)
floppies[tonumber(name)] = contents
end
minetest.register_craftitem("turtle:floppy", {
description = "Floppy disk",
inventory_image = "floppy.png",
stack_max = 1,
})
local progs = {
["Empty"] = string.rep(string.char(0), 16536),
["Forth Boot Disk"] = create_forth_floppy(),
}
minetest.register_node("turtle:floppy_programmator",{
description = "Floppy disk programmator",
tiles = {"floppy_programmator_top.png", "floppy_programmator_bottom.png", "floppy_programmator_right.png",
"floppy_programmator_left.png", "floppy_programmator_back.png", "floppy_programmator_front.png"},
groups = {cracky = 3},
sounds = default.node_sound_stone_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("floppy", 1)
meta:set_int("selected", 1)
local s = "size[8,5.5;]" ..
"dropdown[0,0;5;pselector;"
for key, _ in pairs(progs) do
s = s .. key .. ","
end
s = string.sub(s, 1, -2)
s = s .. ";1]" ..
"button[5,0;2,1;prog;Program]" ..
"list[current_name;floppy;7,0;1,1;]" ..
"list[current_player;main;0,1.5;8,4;]"
meta:set_string("formspec", s)
end,
can_dig = function(pos, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:is_empty("floppy")
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if stack:get_name() == "turtle:floppy" then return 1 end
return 0
end,
on_receive_fields = function(pos, formname, fields, sender)
local meta = minetest.get_meta(pos)
if fields.prog then
local inv = meta:get_inventory()
local prog = progs[fields.pselector]
local stack = inv:get_stack("floppy", 1):to_table()
if stack == nil then return end
2015-02-17 21:01:08 +01:00
if stack.name ~= "turtle:floppy" or stack.count == 0 then return end
local contents, update = handle_floppy_meta(stack)
set_floppy_contents(stack.metadata, prog)
if update then
inv:set_stack("floppy", 1, ItemStack(stack))
end
end
end,
})
function floppy.disk_digiline_receive(inv, channel, msg, disk_channel, send_func)
if channel == disk_channel then
if string.len(msg) ~= 1 and string.len(msg) ~= 65 then return end -- Invalid message, it comes probably from the disk itself
local page = string.byte(msg, 1)
if page == nil then return end
local stack = inv:get_stack("floppy", 1):to_table()
if stack == nil then return end
if stack.name ~= "turtle:floppy" then return end
local floppy_contents, update = handle_floppy_meta(stack)
if update then
inv:set_stack("floppy", 1, ItemStack(stack))
end
msg = string.sub(msg, 2, -1)
if string.len(msg) == 0 then -- read
send_func(string.sub(floppy_contents, page * 64 + 1, page * 64 + 64))
else -- write
floppy_contents = string.sub(floppy_contents, 1, page * 64) ..
msg ..
string.sub(floppy_contents, page * 64 + 65, -1)
set_floppy_contents(stack.metadata, floppy_contents)
end
end
end
minetest.register_node("turtle:disk",{
description = "Disk drive",
paramtype2 = "facedir",
tiles = {"floppy_drive_top.png", "floppy_drive_bottom.png", "floppy_drive_right.png", "floppy_drive_left.png", "floppy_drive_back.png", "floppy_drive_front.png"},
groups = {cracky = 3},
sounds = default.node_sound_stone_defaults(),
digiline =
{
receptor = {},
effector = {action = function(pos, node, channel, msg)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local disk_channel = meta:get_string("channel")
floppy.disk_digiline_receive(inv, channel, msg, disk_channel, function(msg)
digiline:receptor_send(pos, digiline.rules.default, disk_channel, msg)
end)
end},
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size("floppy", 1)
meta:set_string("channel", "")
meta:set_string("formspec", "size[9,5.5;]"..
"field[0,0.5;7,1;channel;Channel:;${channel}]"..
"list[current_name;floppy;8,0;1,1;]"..
"list[current_player;main;0,1.5;8,4;]")
end,
can_dig = function(pos, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:is_empty("floppy")
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if stack:get_name() == "turtle:floppy" then return 1 end
return 0
end,
on_receive_fields = function(pos, formname, fields, sender)
local meta = minetest.get_meta(pos)
fields.channel = fields.channel or meta:get_string("channel")
meta:set_string("channel", fields.channel)
end,
})