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:
parent
f88342c746
commit
22ba0e7fb3
2
API.md
2
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
|
||||
|
23
app_fw.lua
23
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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
})
|
||||
|
@ -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
|
||||
})
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
})
|
||||
|
@ -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
185
block_devices.lua
Normal 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
|
||||
|
||||
|
||||
|
@ -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
|
||||
})
|
4
init.lua
4
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')
|
||||
|
15
node_fw.lua
15
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
|
||||
|
||||
|
@ -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
140
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user