minetest-laptop/block_devices.lua

205 lines
5.5 KiB
Lua

local mod_storage = minetest.get_mod_storage()
local bdev = {}
-- Check hardware capabilities { "hdd", "floppy", "usb", "net", "liveboot" }
function bdev:is_hw_capability(hw_cap)
for i, cap in ipairs(self.os.hwdef.hw_capabilities) do
if cap == hw_cap or cap == hw_cap:sub(18, -1) then --"laptop_removable_*"then
return cap
end
end
return false
end
-- Get RAM
function bdev:get_ram_disk()
if not self.ram_disk then
self.ram_disk = minetest.deserialize(self.os.meta:get_string('laptop_ram')) or {}
end
return self.ram_disk
end
function bdev:free_ram_disk()
self.ram_disk = {}
self:sync()
end
-- Get HDD if exists
function bdev:get_hard_disk()
if self.hard_disk == nil then
if self:is_hw_capability('hdd') then
self.hard_disk = minetest.deserialize(self.os.meta:get_string('laptop_appdata')) or {}
else
self.hard_disk = false
end
end
return self.hard_disk
end
-- Get Removable disk if exists
function bdev:get_removable_disk(removable_type)
if self.removable_disk == nil then
local data = { bdev = self }
data.inv = self.os.meta:get_inventory()
data.inv:set_size("main", 1) -- 1 disk supported
function data:reload(stack)
-- self.inv unchanged
-- self.rtype unchanged (assumption
stack = stack or self.inv:get_stack("main", 1)
if stack then
local def = stack:get_definition()
if def and def.name ~= "" then
self.stack = stack
self.def = def
self.meta = stack:get_meta()
self.os_format = self.meta:get_string("os_format")
if self.os_format == "" then
self.os_format = "none"
end
self.label = self.meta:get_string("description")
if self.label == "" then
self.label = self.def.description
end
for group, _ in pairs(self.def.groups) do
local rtype_chk = self.bdev:is_hw_capability(group)
if not removable_type or removable_type == rtype_chk then
self.rtype = rtype_chk
break
end
end
self.storage = minetest.deserialize(self.meta:get_string("os_storage")) or {}
end
end
end
function data:eject()
if not self.stack then
return false
end
local p = self.bdev.os.pos
local drop_pos = { x=p.x+math.random()*2-1, y=p.y,z=p.z+math.random()*2-1 }
minetest.item_drop(self.stack, nil, drop_pos)
self.stack = nil
return true
end
function data:format_disk(ftype, label)
self.stack = ItemStack(self.def.name)
self.meta = self.stack:get_meta()
self.meta:set_string("os_format", ftype or "")
self.os_format = ftype
self.label = label or ""
end
data:reload()
self.removable_disk = data
end
return self.removable_disk
end
-- Connect to cloud
function bdev:get_cloud_disk(store_name)
if self.cloud_disk == nil or (self.cloud_disk ~= false and not self.cloud_disk[store_name]) then
if self:is_hw_capability('net') then
self.cloud_disk = self.cloud_disk or {}
self.cloud_disk[store_name] = minetest.deserialize(mod_storage:get_string(store_name)) or {}
else
self.cloud_disk = false
return false
end
end
return self.cloud_disk[store_name]
end
-- Get device to boot
function bdev:get_boot_disk()
if self:is_hw_capability('liveboot') then
local drive = self:get_removable_disk()
if drive.stack and drive.os_format == 'boot' then
return 'removable'
end
end
return 'hdd'
end
-- Get app related object from storage "disk_type"
function bdev:get_app_storage(disk_type, store_name)
if disk_type == 'ram' then
local store = self:get_ram_disk()
store[store_name] = store[store_name] or {}
return store[store_name]
elseif disk_type == 'hdd' then
local store = self:get_hard_disk()
if store then
store[store_name] = store[store_name] or {}
return store[store_name]
else
return nil
end
elseif disk_type == 'removable' then
local store = self:get_removable_disk()
if store.stack and (store.os_format == 'data' or store.os_format == 'boot') then
store.storage[store_name] = store.storage[store_name] or {}
return store.storage[store_name]
else
return nil
end
elseif disk_type == 'system' then
local runtime = self:get_app_storage("ram", "os")
runtime.booted_from = runtime.booted_from or self:get_boot_disk()
return self:get_app_storage(runtime.booted_from, store_name)
elseif disk_type == 'cloud' then
return self:get_cloud_disk(store_name) or nil
end
end
-- Save all data if used
function bdev:sync()
-- save RAM
self.os.meta:set_string('laptop_ram', minetest.serialize(self.ram_disk))
self.os.meta:mark_as_private('laptop_ram')
-- save HDD
if self.hard_disk then
self.os.meta:set_string('laptop_appdata', minetest.serialize(self.hard_disk))
self.os.meta:mark_as_private('laptop_appdata')
end
-- save removable
if self.removable_disk then
if self.removable_disk.stack then
if self.removable_disk.def and self.removable_disk.label ~= self.removable_disk.def.description then
self.removable_disk.meta:set_string("description", self.removable_disk.label)
end
if self.removable_disk.storage and next(self.removable_disk.storage) then
self.removable_disk.meta:set_string("os_storage", minetest.serialize(self.removable_disk.storage))
end
end
self.removable_disk.inv:set_stack("main", 1, self.removable_disk.stack)
end
end
-- Save all data if used
function bdev:sync_cloud()
-- Modmeta (Cloud)
if self.cloud_disk then
for store, value in pairs(self.cloud_disk) do
mod_storage:set_string(store, minetest.serialize(value))
end
end
end
-- Get handler
function laptop.get_bdev_handler(mtos)
local bdevobj = {}
for k,v in pairs(bdev) do
bdevobj[k] = v
end
bdevobj.os = mtos
return bdevobj
end