diff --git a/API.md b/API.md index 44708d9..aedb3cb 100644 --- a/API.md +++ b/API.md @@ -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 diff --git a/app_fw.lua b/app_fw.lua index 4983ab7..6bc7351 100644 --- a/app_fw.lua +++ b/app_fw.lua @@ -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 diff --git a/apps/calculator_app.lua b/apps/calculator_app.lua index 6f504e5..4e7945b 100644 --- a/apps/calculator_app.lua +++ b/apps/calculator_app.lua @@ -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 diff --git a/apps/launcher_app.lua b/apps/launcher_app.lua index a792c4c..7865921 100644 --- a/apps/launcher_app.lua +++ b/apps/launcher_app.lua @@ -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, }) diff --git a/apps/launcher_insert_floppy_app.lua b/apps/launcher_insert_floppy_app.lua deleted file mode 100644 index caabb95..0000000 --- a/apps/launcher_insert_floppy_app.lua +++ /dev/null @@ -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 -}) diff --git a/apps/launcher_settings_app.lua b/apps/launcher_settings_app.lua index 666b9ec..374b752 100644 --- a/apps/launcher_settings_app.lua +++ b/apps/launcher_settings_app.lua @@ -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: for selected or DCL: for double-clicked diff --git a/apps/mail_app.lua b/apps/mail_app.lua index f904aff..c90939f 100644 --- a/apps/mail_app.lua +++ b/apps/mail_app.lua @@ -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 diff --git a/apps/removable_app.lua b/apps/removable_app.lua index fd193de..a6af7bc 100644 --- a/apps/removable_app.lua +++ b/apps/removable_app.lua @@ -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, }) diff --git a/apps/stickynote_app.lua b/apps/stickynote_app.lua index 69b6ba0..0de011f 100644 --- a/apps/stickynote_app.lua +++ b/apps/stickynote_app.lua @@ -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 diff --git a/block_devices.lua b/block_devices.lua new file mode 100644 index 0000000..6224beb --- /dev/null +++ b/block_devices.lua @@ -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 + + + diff --git a/demo_apps.lua b/demo_apps.lua deleted file mode 100644 index 8b0cf21..0000000 --- a/demo_apps.lua +++ /dev/null @@ -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 -}) diff --git a/init.lua b/init.lua index 2420976..5a224c0 100644 --- a/init.lua +++ b/init.lua @@ -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') diff --git a/node_fw.lua b/node_fw.lua index 864c2cc..149ff38 100644 --- a/node_fw.lua +++ b/node_fw.lua @@ -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 diff --git a/nodes.lua b/nodes.lua index 2bbafe0..e13edd6 100644 --- a/nodes.lua +++ b/nodes.lua @@ -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", diff --git a/os.lua b/os.lua index 48d6eca..17fbcd5 100644 --- a/os.lua +++ b/os.lua @@ -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