Big API break

Introduce block device handling object to handle different storage types and multiboot
still needs to be tested and docmentation adjusted
This commit is contained in:
Alexander Weber 2017-12-15 00:30:35 +01:00
parent f88342c746
commit 22ba0e7fb3
15 changed files with 297 additions and 253 deletions

2
API.md
View File

@ -8,7 +8,7 @@
- `hwdef.sequence = { "variant_1_name", "variant_2_name", "variant_3_name" }` On punch swaps sequence. the first variant is in creative inventory
- `hwdef.custom_launcer` - optional - custom launcher name
- `hwdef.custom_theme` - optional - custom initial theme name
- `hwdef.removable_capability` - optional. Table with compatible removable groups. Supported "floppy" or "usb". Default { "floppy", "usb" }
- `hwdef.hw_capabilities` - optional. Table with hardware capabilities. Default is all: { "hdd", "floppy", "usb", "net", "liveboot" }
- `hwdef.node_defs = {
variant_1_name = {
hw_state = "resume", "power_on" or "power_off", -- Hardware state

View File

@ -47,29 +47,10 @@ function app_class:receive_data(method, reshow, sender, ...)
return ret
end
-- Get persitant storage table
function app_class:get_storage_ref(app_name)
local store_name = app_name or self.name
if not self.os.appdata[store_name] then
self.os.appdata[store_name] = {}
end
return self.os.appdata[store_name]
end
-- Get persitant storage table
function app_class:get_cloud_storage_ref(app_name)
return self.os:connect_to_cloud(app_name)
end
-- Get persitant storage table
function app_class:get_removable_storage_ref(app_name)
return self.os:connect_to_removable(app_name)
end
-- Back to previous app in stack
function app_class:back_app()
self.os.appdata.os.current_app = self.os:appstack_pop()
self.os:set_app(self.os.appdata.os.current_app)
self.os.sysram.current_app = self.os:appstack_pop()
self.os:set_app(self.os.sysram.current_app)
end
-- Exit current app and back to launcher

View File

@ -3,7 +3,7 @@ laptop.register_app("calculator", {
app_icon = "laptop_calculator.png",
app_info = "Calculate things",
formspec_func = function(app, mtos)
local data = app:get_storage_ref()
local data = mtos.bdev:get_app_storage('ram', 'calculator')
if not data.tab then
data.tab = {}
@ -51,7 +51,7 @@ laptop.register_app("calculator", {
end,
receive_fields_func = function(app, mtos, sender, fields)
local data = app:get_storage_ref()
local data = mtos.bdev:get_app_storage('ram', 'calculator')
local entry = data.tab[#data.tab]
if fields.number then

View File

@ -3,6 +3,28 @@ laptop.register_app("launcher", {
-- app_name = "Main launcher", -- not in launcher list
fullscreen = true,
formspec_func = function(launcher_app, mtos)
-- no system found. Error
if not mtos.sysdata then
local formspec = "size[10,7]background[10,7;0,0;laptop_launcher_insert_floppy.png;true]"..
"listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]"..
"list[nodemeta:"..mtos.pos.x..','..mtos.pos.y..','..mtos.pos.z..";main;2.5,3;1,1;]" ..
"list[current_player;main;0,6.5;8,1;]" ..
"listring[nodemeta:"..mtos.pos.x..','..mtos.pos.y..','..mtos.pos.z..";main]" ..
"listring[current_player;main]"
local idata = mtos.bdev:get_removable_disk()
if idata then
if idata.os_format == "boot" then
-- boot "default" launcher
return laptop.apps.launcher.formspec_func(launcher_app, mtos)
else
formspec = formspec .. "label[0,1.7;Disk found but not formatted to boot]"
end
end
return formspec
end
local c_row_count = 4
local i = 0
@ -32,11 +54,11 @@ laptop.register_app("launcher", {
if mtos.theme.app_bg then
formspec = formspec..'background[0,0;15,10;'..mtos.theme.app_bg..';true]'
end
if #mtos.appdata.os.stack > 0 then
if #mtos.sysram.stack > 0 then
formspec = formspec..'image_button[-0.29,-0.31;1.09,0.61;'..mtos.theme.back_button..';os_back;<]'
end
if app.app_info then
if #mtos.appdata.os.stack > 0 then
if #mtos.sysram.stack > 0 then
formspec = formspec.."label[0.8,-0.29;"..app.app_info.."]"
else
formspec = formspec.."label[-0.1,-0.29;"..app.app_info.."]"
@ -52,5 +74,5 @@ laptop.register_app("launcher", {
break
end
end
end
end,
})

View File

@ -1,28 +0,0 @@
laptop.register_app("launcher_insert_floppy", {
fullscreen = true,
formspec_func = function(launcher_app, mtos) --redefine the formspec
local formspec = "size[10,7]background[10,7;0,0;laptop_launcher_insert_floppy.png;true]"..
"listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]"..
"list[nodemeta:"..mtos.pos.x..','..mtos.pos.y..','..mtos.pos.z..";main;2.5,3;1,1;]" ..
"list[current_player;main;0,6.5;8,1;]" ..
"listring[nodemeta:"..mtos.pos.x..','..mtos.pos.y..','..mtos.pos.z..";main]" ..
"listring[current_player;main]"
local idata = mtos:get_removable_data()
if idata then
if idata.os_format == "OldOS" then
-- boot "default" launcher
return laptop.apps.launcher.formspec_func(launcher_app, mtos)
else
formspec = formspec .. "label[0,1.7;Disk found but not formatted to boot]"
end
end
return formspec
end,
appwindow_formspec_func = function(...)
return laptop.apps.launcher.appwindow_formspec_func(...)
end,
receive_fields_func = function(...)
return laptop.apps.launcher.receive_fields_func(...)
end
})

View File

@ -13,7 +13,7 @@ laptop.register_app("launcher_settings", {
app_info = "Change the computer's settings.",
formspec_func = function(app, mtos)
local settings_data = app:get_storage_ref()
local settings_data = mtos.bdev:get_app_storage('ram', 'launcher_settings')
-- Change background setting
local current_theme_name = settings_data.selected_theme or mtos:get_theme().name or "default"
@ -47,7 +47,7 @@ laptop.register_app("launcher_settings", {
end,
receive_fields_func = function(app, mtos, sender, fields)
local settings_data = app:get_storage_ref()
local settings_data = mtos.bdev:get_app_storage('ram', 'launcher_settings')
if fields.sel_theme then
-- CHG:<idx> for selected or DCL:<idx> for double-clicked

View File

@ -5,23 +5,28 @@ laptop.register_app("mail", {
app_icon = "laptop_email_letter.png",
app_info = "Write mails to other players",
formspec_func = function(app, mtos)
local cloud = app:get_cloud_storage_ref("mail")
if not mtos.appdata.os.last_player then
local cloud = mtos.bdev:get_app_storage('cloud', 'mail')
if not cloud then
mtos:set_app("mail:nonet")
return false
end
if not mtos.sysram.last_player then
mtos:set_app() -- no player. Back to launcher
return false
end
if not cloud[mtos.appdata.os.last_player] then
if not cloud[mtos.sysram.last_player] then
mtos:set_app("mail:newplayer")
return false
end
local account = cloud[mtos.appdata.os.last_player]
local account = cloud[mtos.sysram.last_player]
account.selected_box = account.selected_box or "inbox"
account.selected_index = nil -- will be new determinated by selectedmessage
local box = account[account.selected_box] -- inbox or outbox
local formspec =
"label[4,-0.31;Welcome "..mtos.appdata.os.last_player.."]"..
"label[4,-0.31;Welcome "..mtos.sysram.last_player.."]"..
"tablecolumns[" ..
"image,align=center,1=laptop_mail.png,2=laptop_mail_read.png;".. --icon column
"color;".. -- subject and date color
@ -114,13 +119,13 @@ laptop.register_app("mail", {
return formspec
end,
receive_fields_func = function(app, mtos, sender, fields)
if sender:get_player_name() ~= mtos.appdata.os.last_player then
if sender:get_player_name() ~= mtos.sysram.last_player then
mtos:set_app() -- wrong player. Back to launcher
return
end
local cloud = app:get_cloud_storage_ref("mail")
local account = cloud[mtos.appdata.os.last_player]
local cloud = mtos.bdev:get_app_storage('cloud', 'mail')
local account = cloud[mtos.sysram.last_player]
if not account then
mtos:set_app() -- wrong player. Back to launcher
return
@ -182,17 +187,17 @@ laptop.register_app("mail", {
laptop.register_view("mail:newplayer", {
formspec_func = function(app, mtos)
return mtos.theme:get_label('1,3', "No mail account for player "..mtos.appdata.os.last_player.. " found. Do you like to create a new account?")..
return mtos.theme:get_label('1,3', "No mail account for player "..mtos.sysram.last_player.. " found. Do you like to create a new account?")..
mtos.theme:get_button('1,4;3,1', 'major', 'create', 'Create account')
end,
receive_fields_func = function(app, mtos, sender, fields)
if sender:get_player_name() ~= mtos.appdata.os.last_player then
if sender:get_player_name() ~= mtos.sysram.last_player then
mtos:set_app() -- wrong player. Back to launcher
return
end
if fields.create then
local cloud = app:get_cloud_storage_ref("mail")
cloud[mtos.appdata.os.last_player] = {
cloud[mtos.sysram.last_player] = {
inbox = {},
sentbox = {}
}
@ -203,11 +208,20 @@ laptop.register_view("mail:newplayer", {
end
})
laptop.register_view("mail:nonet", {
formspec_func = function(app, mtos)
return mtos.theme:get_label('1,3', "No internet available on this computer")
end,
receive_fields_func = function(app, mtos, sender, fields)
app:exit_app()
end
})
-- Write new mail
laptop.register_view("mail:compose", {
formspec_func = function(app, mtos)
local cloud = app:get_cloud_storage_ref("mail")
local account = cloud[mtos.appdata.os.last_player]
local cloud = mtos.bdev:get_app_storage('cloud', 'mail')
local account = cloud[mtos.sysram.last_player]
account.newmessage = account.newmessage or {}
local message = account.newmessage
@ -239,18 +253,18 @@ laptop.register_view("mail:compose", {
return formspec
end,
receive_fields_func = function(app, mtos, sender, fields)
if sender:get_player_name() ~= mtos.appdata.os.last_player then
if sender:get_player_name() ~= mtos.sysram.last_player then
mtos:set_app() -- wrong player. Back to launcher
return
end
local cloud = app:get_cloud_storage_ref("mail")
local account = cloud[mtos.appdata.os.last_player]
local cloud = mtos.bdev:get_app_storage('cloud', 'mail')
local account = cloud[mtos.sysram.last_player]
account.newmessage = account.newmessage or {}
local message = account.newmessage
message.receiver = fields.receiver or message.receiver
message.sender = mtos.appdata.os.last_player
message.sender = mtos.sysram.last_player
message.time = os.time()
message.subject = fields.subject or message.subject
message.body = fields.body or message.body

View File

@ -11,7 +11,8 @@ laptop.register_app("removable", {
"listring[nodemeta:"..mtos.pos.x..','..mtos.pos.y..','..mtos.pos.z..";main]" ..
"listring[current_player;main]"
local idata = mtos:get_removable_data()
mtos.bdev.removable_disk = nil -- force reading
local idata = mtos.bdev:get_removable_disk()
if idata then
-- change label
formspec = formspec .. mtos.theme:get_label('0,1.2', idata.def.description).."field[2,0.7;4,1;label;Label:;"..idata.label.."]"..
@ -37,7 +38,7 @@ laptop.register_app("removable", {
receive_fields_func = function(app, mtos, sender, fields)
local idata = mtos:get_removable_data()
local idata = mtos.bdev:get_removable_disk()
if idata then
if fields.set_label then
idata.label = fields.label
@ -53,15 +54,15 @@ laptop.register_app("removable", {
idata.meta:set_string("os_format", "backup")
idata.meta:set_string("backup_data", mtos.meta:get_string('laptop_appdata'))
elseif fields.format == "OldOS" then
idata.meta:set_string("os_format", "OldOS")
idata.meta:set_string("os_format", "boot")
end
elseif fields.restore then
mtos.appdata = minetest.deserialize(idata.meta:get_string("backup_data")) or {}
mtos.appdata.os.current_app = nil
mtos:save()
-- TODO was soll wiederhergestellt werden?
mtos.meta:set_string('laptop_appdata', idata.meta:get_string("backup_data"))
mtos.bdev = laptop.get_bdev_handler(mtos)
laptop.os_get(mtos.pos):power_on() --reboot
end
mtos:set_removable_data()
end
mtos.bdev:sync()
end,
})

View File

@ -3,7 +3,7 @@ laptop.register_app("stickynote", {
app_icon = "laptop_notes_pad.png",
app_info = "Write notes in a text document.",
formspec_func = function(app, mtos)
local data = app:get_storage_ref()
local data = mtos.bdev:get_app_storage('system', 'stickynote')
data.files = data.files or {}
if data.selected_file then
@ -43,7 +43,7 @@ laptop.register_app("stickynote", {
end,
receive_fields_func = function(app, mtos, sender, fields)
if fields.text then
local data = app:get_storage_ref()
local data = mtos.bdev:get_app_storage('system', 'stickynote')
data.text = fields.text
end
end

185
block_devices.lua Normal file
View File

@ -0,0 +1,185 @@
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.os.meta:set_string('laptop_ram','')
self.ram_disk = nil
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 inv = self.os.meta:get_inventory()
inv:set_size("main", 1) -- 1 disk supported
local stack = inv:get_stack("main", 1)
local is_compatible = false
if stack then
local def = stack:get_definition()
local rtype
if def and def.name ~= "" then
for group, _ in pairs(def.groups) do
if not removable_type or removable_type == self:is_hw_capability(group) then
is_compatible = true
end
end
end
if is_compatible then
local stackmeta = stack:get_meta()
local os_format = stackmeta:get_string("os_format")
if os_format == "" then
os_format = "none"
end
local data = {
inv = inv,
def = def,
stack = stack,
meta = stackmeta,
os_format = os_format,
rtype = rtype,
storage = minetest.deserialize(stackmeta:get_string("os_storage")) or {},
}
data.label = data.meta:get_string("description")
if not data.label or data.label == "" then
data.label = def.description
end
self.removable_disk = data
end
end
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 removable = self:get_removable_disk()
if removable and removable.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 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
if self.system_disk == nil then
local ram = self:get_ram_disk()
local boot
if ram.os then
boot = ram.os.booted_from
end
boot = boot or self:get_boot_disk()
self.system_disk = self:get_app_storage(boot, store_name)
end
return self.system_disk
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))
-- save HDD
if self.hard_disk then
self.os.meta:set_string('laptop_appdata', minetest.serialize(self.hard_disk))
end
-- save removable
if self.removable_disk then
local data = self.removable_disk
if data.label ~= data.def.description then
data.meta:set_string("description", data.label)
end
data.meta:set_string("os_storage", minetest.serialize(data.storage))
data.inv:set_stack("main", 1, data.stack)
end
-- 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 = table.copy(bdev)
bdevobj.os = mtos
return bdevobj
end

View File

@ -1,43 +0,0 @@
laptop.register_app("demo1", {
app_name = "Demo App",
app_icon = "laptop_setting_wrench.png",
app_info = "The first and simple demo app",
formspec_func = function(app, mtos)
return mtos.theme:get_button('5,5;3,1', 'major', 'next', 'Second screen')
end,
receive_fields_func = function(app, mtos, sender, fields)
if fields.next then
mtos:set_app("demo1_view2")
end
end
})
laptop.register_view("demo1_view2", {
app_info = "Second screen in Demo App 1",
formspec_func = function(app, mtos)
return mtos.theme:get_label('1,5', "Use the framework buttons to navigate back or cancel")
end,
receive_fields_func = function(app, mtos, sender, fields)
end
})
laptop.register_app("demo2", {
app_name = "Demo App 2",
formspec_func = function(app, mtos)
local data = app:get_storage_ref()
data.counter = data.counter or 1
return 'button[3,1;5,1;count;Click: '..data.counter..']'..
'button[3,3;5,1;back;Back to launcher]'
end,
receive_fields_func = function(app, mtos, sender, fields)
if fields.count then
local data = app:get_storage_ref()
data.counter = data.counter + 1
elseif fields.back then
app:exit_app()
end
end
})

View File

@ -1,11 +1,9 @@
laptop = {}
laptop.class_lib = {}
dofile(minetest.get_modpath('laptop')..'/themes.lua')
dofile(minetest.get_modpath('laptop')..'/block_devices.lua')
dofile(minetest.get_modpath('laptop')..'/app_fw.lua')
dofile(minetest.get_modpath('laptop')..'/os.lua')
dofile(minetest.get_modpath('laptop')..'/node_fw.lua')
dofile(minetest.get_modpath('laptop')..'/nodes.lua')
dofile(minetest.get_modpath('laptop')..'/items.lua')
-- uncomment this line to disable demo apps in production
--dofile(minetest.get_modpath('laptop')..'/demo_apps.lua')

View File

@ -75,9 +75,8 @@ local function allow_metadata_inventory_put(pos, listname, index, stack, player)
local def = stack:get_definition()
local allowed_stacksize = 0
if def then
local supported = mtos.hwdef.removable_capability or {"usb", "floppy"}
for _, cap in ipairs(supported) do
if def.groups["laptop_removable_"..cap] then
for group, _ in pairs(def.groups) do
if mtos.bdev:is_hw_capability(group) then
allowed_stacksize = 1
end
end
@ -142,15 +141,19 @@ function laptop.register_hardware(name, hwdef)
minetest.register_node(nodename, def)
-- set node configuration for hooks
laptop.node_config[nodename] = table.copy(hwdef)
local merged_hwdef = table.copy(hwdef)
for k,v in pairs(hwdef.node_defs[variant]) do
laptop.node_config[nodename][k] = v
merged_hwdef[k] = v
end
local next_seq = hwdef.sequence[idx+1] or hwdef.sequence[1]
local next_node = name.."_"..next_seq
if next_node ~= nodename then
laptop.node_config[nodename].next_node = next_node
merged_hwdef.next_node = next_node
end
-- Defaults
merged_hwdef.hw_capabilities = merged_hwdef.hw_capabilities or {"hdd", "floppy", "usb", "net", "liveboot"}
laptop.node_config[nodename] = merged_hwdef
end
end

View File

@ -2,7 +2,7 @@ laptop.register_hardware("laptop:core", {
description = "CP Core",
infotext = 'CP Core',
sequence = { "closed", "open", "open_on" },
removable_capability = { 'usb' },
hw_capabilities = { 'hdd', 'usb', 'net' },
node_defs = {
["open"] = {
hw_state = "power_off",
@ -75,7 +75,7 @@ laptop.register_hardware("laptop:cube", {
infotext = "CUBE PC",
sequence = { "off", "on"},
custom_theme = "Red",
removable_capability = { "floppy" },
hw_capabilities = { "hdd", "floppy", "net", "liveboot" },
node_defs = {
["on"] = {
hw_state = "power_on",
@ -258,8 +258,7 @@ laptop.register_hardware("laptop:monitor3", {
description = "Pentium 3",
infotext = "Pentium 3",
sequence = { "off", "on"},
custom_launcher = "launcher_insert_floppy",
removable_capability = { "floppy" },
hw_capabilities = { "floppy", "liveboot" },
node_defs = {
["on"] = {
hw_state = "power_on",

140
os.lua
View File

@ -5,8 +5,6 @@ local os_class = {}
os_class.__index = os_class
laptop.class_lib.os = os_class
local mod_storage = minetest.get_mod_storage()
-- Swap the node
function os_class:swap_node(new_node_name)
local node = minetest.get_node(self.pos)
@ -23,6 +21,8 @@ end
-- Power on the system and start the launcher
function os_class:power_on(new_node_name)
self.bdev:free_ram_disk()
self.sysram = self.bdev:get_app_storage('ram', 'os')
self:swap_node(new_node_name)
self:set_app() --launcher
end
@ -30,7 +30,7 @@ end
-- Power on the system / and resume last running app
function os_class:resume(new_node_name)
self:swap_node(new_node_name)
self:set_app(self.appdata.os.current_app)
self:set_app(self.sysram.current_app)
end
-- Power off the system
@ -47,38 +47,40 @@ end
-- Get given or current theme
function os_class:get_theme(theme)
local theme_sel = theme or self.appdata.os.theme
return laptop.get_theme(theme_sel)
if not theme and self.sysdata then
theme = self.sysdata.theme
end
return laptop.get_theme(theme)
end
-- Set current theme
function os_class:set_theme(theme)
if laptop.themes[theme] then
self.appdata.os.theme = theme
self.sysdata.theme = theme
self.theme = self:get_theme()
self:save()
self:swap_node()
self:save()
end
end
-- Add app to stack (before starting new)
function os_class:appstack_add(appname)
table.insert(self.appdata.os.stack, appname)
table.insert(self.sysram.stack, appname)
end
-- Get last app from stack
function os_class:appstack_pop()
local ret
if #self.appdata.os.stack > 0 then
ret = self.appdata.os.stack[#self.appdata.os.stack]
table.remove(self.appdata.os.stack, #self.appdata.os.stack)
if #self.sysram.stack > 0 then
ret = self.sysram.stack[#self.sysram.stack]
table.remove(self.sysram.stack, #self.sysram.stack)
end
return ret
end
-- Free stack
function os_class:appstack_free()
self.appdata.os.stack = {}
self.sysram.stack = {}
end
-- Get new app instance
@ -99,13 +101,12 @@ function os_class:set_app(appname)
local newapp = appname or launcher
if newapp == launcher then
self:appstack_free()
elseif self.appdata.os.current_app and
self.appdata.os.current_app ~= launcher and
self.appdata.os.current_app ~= newapp then
self:appstack_add(self.appdata.os.current_app)
elseif self.sysram.current_app and
self.sysram.current_app ~= launcher and
self.sysram.current_app ~= newapp then
self:appstack_add(self.sysram.current_app)
end
self.appdata.os.current_app = newapp
self.sysram.current_app = newapp
local app = self:get_app(newapp)
local formspec = app:get_formspec()
if formspec ~= false then
@ -116,11 +117,11 @@ end
-- Handle input processing
function os_class:pass_to_app(method, reshow, sender, ...)
local appname = self.appdata.os.current_app or self.hwdef.custom_launcher or "launcher"
local appname = self.sysram.current_app or self.hwdef.custom_launcher or "launcher"
local app = self:get_app(appname)
local ret = app:receive_data(method, reshow, sender, ...)
self.appdata.os.last_player = sender:get_player_name()
if self.appdata.os.current_app == appname and reshow then
self.sysram.last_player = sender:get_player_name()
if self.sysram.current_app == appname and reshow then
local formspec = app:get_formspec()
if formspec ~= false then
self.meta:set_string('formspec', formspec)
@ -130,96 +131,8 @@ function os_class:pass_to_app(method, reshow, sender, ...)
return ret
end
-- Get Low-Level access to inventory slot
function os_class:get_removable_data(media_type)
self.removable_data = nil
local inv = self.meta:get_inventory()
inv:set_size("main", 1) -- 1 disk supported
local stack = inv:get_stack("main", 1)
if stack then
local def = stack:get_definition()
if def and def.name ~= "" then
local stackmeta = stack:get_meta()
local os_format = stackmeta:get_string("os_format")
if os_format == "" then
os_format = "none"
end
if not media_type or -- no parameter asked
def.groups["laptop_removable_"..media_type] or --usb or floppy
media_type == os_format then -- "none", "OldOS", "backup", "filesystem"
local data = {
inv = inv,
def = def,
stack = stack,
meta = stackmeta,
os_format = os_format,
}
data.label = data.meta:get_string("description")
if not data.label or data.label == "" then
data.label = def.description
end
self.removable_data = data
return data
end
end
end
end
-- Store data to inventory slot item (low-level)
function os_class:set_removable_data()
if self.removable_data then
local data = self.removable_data
if data.label ~= data.def.description then
data.meta:set_string("description", data.label)
end
data.inv:set_stack("main", 1, data.stack)
end
end
-- Get mod storage as (=internet / cloud)
function os_class:connect_to_cloud(store_name)
self.cloud_store = self.cloud_store or {}
self.cloud_store[store_name] = self.cloud_store[store_name] or
minetest.deserialize(mod_storage:get_string(store_name)) or {}
return self.cloud_store[store_name]
end
-- Connect to app storage on removable
function os_class:connect_to_removable(store_name)
local data = self.removable_data or self:get_removable_data("data")
if not data then
self.removable_app_data = nil
return
end
self.removable_app_data = self.removable_app_data or {}
self.removable_app_data[store_name] = self.removable_app_data[store_name] or
minetest.deserialize(data.meta:get_string(store_name)) or {}
return self.cloud_store[store_name]
end
-- Save the data
function os_class:save()
-- Nodemata (HDD)
self.meta:set_string('laptop_appdata', minetest.serialize(self.appdata))
-- Modmeta (Cloud)
if self.cloud_store then
for store, value in pairs(self.cloud_store) do
mod_storage:set_string(store, minetest.serialize(value))
end
self.cloud_store = nil
end
-- Itemstack meta (removable)
if self.removable_data then
if self.removable_app_data then
for store, value in pairs(self.removable_app_data) do
data.meta:set_string(store, minetest.serialize(value))
end
end
self:set_removable_data()
end
self.removable_data = nil
self.bdev:sync()
end
-----------------------------------------------------
@ -232,10 +145,9 @@ function laptop.os_get(pos)
self.node = minetest.get_node(pos)
self.hwdef = laptop.node_config[self.node.name]
self.meta = minetest.get_meta(pos)
self.appdata = minetest.deserialize(self.meta:get_string('laptop_appdata')) or {}
self.appdata.launcher = self.appdata.launcher or {}
self.appdata.os = self.appdata.os or {}
self.appdata.os.stack = self.appdata.os.stack or {}
self.bdev = laptop.get_bdev_handler(self)
self.sysram = self.bdev:get_app_storage('ram', 'os')
self.sysdata = self.bdev:get_app_storage('system', 'os')
self.theme = self:get_theme()
return self
end