Add files via upload
This commit is contained in:
parent
db8886ef3b
commit
0a2c8d6e37
16
API.md
16
API.md
@ -8,6 +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.node_defs = {
|
||||
variant_1_name = {
|
||||
hw_state = "resume", "power_on" or "power_off", -- Hardware state
|
||||
@ -38,10 +39,10 @@ Usable from node functions, from apps or outsite
|
||||
- `mtos:save()` - Store all app-data to nodemeta. Called mostly internally so no explicit call necessary
|
||||
- `mtos:get_app(appname)`- Get the app instance
|
||||
- `mtos:set_app(appname)` - Start/Enable/navigate to appname. If no appname given the launcher is called
|
||||
- `mtos:receive_fields(fields, sender)` - Should be called from node.on_receive_fields to get the apps interactive
|
||||
- `mtos:get_theme(theme)`- Get theme data current or requested (theme parameter is optional)
|
||||
- `mtos:set_theme(theme)`- Activate theme
|
||||
|
||||
- `mtos:get_removable_data(media_type)` - Access to the item in node inventory (low-level). if media_type is given (item type "usb" or "floppy", or os_format) the method returns only if the type matches
|
||||
- `mtos:set_removable_data()` - Store changes on low-level removable data
|
||||
|
||||
## App Definition
|
||||
`laptop.register_app(internal_shortname, { definitiontable })` - add a new app or view
|
||||
@ -52,7 +53,7 @@ Usable from node functions, from apps or outsite
|
||||
- `view` - (boolean) The definition is a view. That means the app/view is not visible in launcher
|
||||
- `formspec_func(app, mtos)` - Function, should return the app formspec (mandatory) During definition the "app" and the "mtos" are available
|
||||
- `appwindow_formspec_func(launcher_app, app, mtos)`- Only custom launcher app: App background / Window decorations and buttons
|
||||
- `receive_fields_func(app, mtos, fields, sender)` Function for input processing. The "app" and the "mtos" are available inside the call
|
||||
- `receive_fields_func(app, mtos, sender, fields)` Function for input processing. The "app" and the "mtos" are available inside the call
|
||||
`laptop.register_view(internal_shortname, { definitiontable })` - add a new app or view
|
||||
same as register_app, but the view flag is set. app_name and app_icon not necessary
|
||||
|
||||
@ -78,3 +79,12 @@ Definitiontable:
|
||||
`function laptop.get_theme(theme_name)`
|
||||
- `theme:get_button(area, prefix, code, text)` get a themed [prefix]_button in area 'x,y;w,h' with code an text
|
||||
- `theme:get_label(pos, text)` get a themed label text starting at pos 'x,y'
|
||||
|
||||
## Low-level Removable data
|
||||
`data = mtos:get_removable_data()`
|
||||
- `label` - Meda label. Item name by default
|
||||
- `def` - Registered item definition (read-only)
|
||||
- `inv` - node inventory
|
||||
- `stack` - The item stack
|
||||
- `meta` - Stack metadata
|
||||
- `os_format`- The format type: "none", "OldOS", "backup", "filesystem" (read-only)
|
||||
|
18
app_fw.lua
18
app_fw.lua
@ -29,16 +29,20 @@ function app_class:get_formspec()
|
||||
end
|
||||
|
||||
-- internally used: process input
|
||||
function app_class:receive_fields(fields, sender)
|
||||
function app_class:receive_data(method, reshow, sender, ...)
|
||||
local ret
|
||||
if self.receive_fields_func then
|
||||
ret = self.receive_fields_func(self, self.os, fields, sender)
|
||||
|
||||
if self[method] then
|
||||
ret = self[method](self, self.os, sender, ...)
|
||||
end
|
||||
|
||||
if fields.os_back then
|
||||
self:back_app()
|
||||
elseif fields.os_exit then
|
||||
self:exit_app()
|
||||
if method == "receive_fields_func" then
|
||||
local fields = ...
|
||||
if fields.os_back then
|
||||
self:back_app()
|
||||
elseif fields.os_exit then
|
||||
self:exit_app()
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
@ -6,7 +6,7 @@ laptop.register_app("demo1", {
|
||||
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, fields, sender)
|
||||
receive_fields_func = function(app, mtos, sender, fields)
|
||||
if fields.next then
|
||||
mtos:set_app("demo1_view2")
|
||||
end
|
||||
@ -18,7 +18,7 @@ laptop.register_view("demo1_view2", {
|
||||
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, fields, sender)
|
||||
receive_fields_func = function(app, mtos, sender, fields)
|
||||
end
|
||||
})
|
||||
|
||||
@ -32,7 +32,7 @@ laptop.register_app("demo2", {
|
||||
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, fields, sender)
|
||||
receive_fields_func = function(app, mtos, sender, fields)
|
||||
if fields.count then
|
||||
local data = app:get_storage_ref()
|
||||
data.counter = data.counter + 1
|
||||
|
1
init.lua
1
init.lua
@ -5,6 +5,7 @@ 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')
|
||||
|
14
items.lua
Normal file
14
items.lua
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
minetest.register_craftitem("laptop:floppy", {
|
||||
description = 'High density floppy',
|
||||
inventory_image = "laptop_diskette.png",
|
||||
groups = {laptop_removable_floppy = 1},
|
||||
stack_max = 1,
|
||||
})
|
||||
|
||||
minetest.register_craftitem("laptop:usbstick", {
|
||||
description = 'USB storage stick',
|
||||
inventory_image = "laptop_usb.png",
|
||||
groups = {laptop_removable_usb = 1},
|
||||
stack_max = 1,
|
||||
})
|
87
node_fw.lua
87
node_fw.lua
@ -2,29 +2,29 @@
|
||||
laptop.node_config = {}
|
||||
|
||||
local function after_place_node(pos, placer, itemstack, pointed_thing)
|
||||
local appdata = minetest.deserialize(itemstack:get_meta():get_string("laptop_appdata"))
|
||||
if appdata then
|
||||
local mtos = laptop.os_get(pos)
|
||||
mtos.appdata = appdata
|
||||
mtos.appdata.launcher = mtos.appdata.launcher or {}
|
||||
mtos.appdata.os = mtos.appdata.os or {}
|
||||
mtos.appdata.os.stack = mtos.appdata.os.stack or {}
|
||||
mtos:save()
|
||||
local save = minetest.deserialize(itemstack:get_meta():get_string("laptop_metadata"))
|
||||
if save then
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:from_table(save.fields)
|
||||
meta:get_inventory():set_list("main", save.invlist)
|
||||
end
|
||||
end
|
||||
|
||||
local function after_dig_node(pos, oldnode, oldmetadata, digger)
|
||||
local appdata = oldmetadata.fields['laptop_appdata']
|
||||
if appdata then
|
||||
local item_name = minetest.registered_items[oldnode.name].drop or oldnode.name
|
||||
local inventory = digger:get_inventory()
|
||||
for idx = inventory:get_size("main"), 1, -1 do
|
||||
local stack = inventory:get_stack("main", idx)
|
||||
if stack:get_name() == item_name and stack:get_meta():get_string("laptop_appdata") == "" then
|
||||
stack:get_meta():set_string("laptop_appdata", appdata)
|
||||
digger:get_inventory():set_stack("main", idx, stack)
|
||||
break
|
||||
end
|
||||
local save = { fields = oldmetadata.fields, invlist = {} }
|
||||
if oldmetadata.inventory and oldmetadata.inventory.main then
|
||||
for _, stack in ipairs(oldmetadata.inventory.main) do
|
||||
table.insert(save.invlist, stack:to_string())
|
||||
end
|
||||
end
|
||||
|
||||
local item_name = minetest.registered_items[oldnode.name].drop or oldnode.name
|
||||
local inventory = digger:get_inventory()
|
||||
for idx, stack in ipairs(inventory:get_list("main")) do
|
||||
if stack:get_name() == item_name and stack:get_meta():get_string("laptop_metadata") == "" then
|
||||
stack:get_meta():set_string("laptop_metadata", minetest.serialize(save))
|
||||
digger:get_inventory():set_stack("main", idx, stack)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -45,6 +45,7 @@ local function on_construct(pos)
|
||||
end
|
||||
|
||||
local function on_punch(pos, node, puncher)
|
||||
-- TODO: Check if wielded item is an removable. Replace stack in this case
|
||||
local mtos = laptop.os_get(pos)
|
||||
local hwdef = laptop.node_config[node.name]
|
||||
if hwdef.next_node then
|
||||
@ -61,7 +62,47 @@ end
|
||||
|
||||
local function on_receive_fields(pos, formname, fields, sender)
|
||||
local mtos = laptop.os_get(pos)
|
||||
mtos:receive_fields(fields, sender)
|
||||
mtos:pass_to_app("receive_fields_func", true, sender, fields)
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local mtos = laptop.os_get(pos)
|
||||
return mtos:pass_to_app("allow_metadata_inventory_move", false, player, from_list, from_index, to_list, to_index, count) or 0
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
local mtos = laptop.os_get(pos)
|
||||
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
|
||||
allowed_stacksize = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
return mtos:pass_to_app("allow_metadata_inventory_put", false, player, listname, index, stack) or allowed_stacksize
|
||||
end
|
||||
|
||||
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
local mtos = laptop.os_get(pos)
|
||||
return mtos:pass_to_app("allow_metadata_inventory_take", false, player, listname, index, stack) or 1 -- by default removal allowed
|
||||
end
|
||||
|
||||
local function on_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local mtos = laptop.os_get(pos)
|
||||
mtos:pass_to_app("on_metadata_inventory_move", true, player, from_list, from_index, to_list, to_index, count)
|
||||
end
|
||||
|
||||
local function on_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
local mtos = laptop.os_get(pos)
|
||||
mtos:pass_to_app("on_metadata_inventory_put", true, player, listname, index, stack)
|
||||
end
|
||||
|
||||
local function on_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
local mtos = laptop.os_get(pos)
|
||||
mtos:pass_to_app("on_metadata_inventory_take", true, player, listname, index, stack)
|
||||
end
|
||||
|
||||
function laptop.register_hardware(name, hwdef)
|
||||
@ -89,6 +130,12 @@ function laptop.register_hardware(name, hwdef)
|
||||
def.on_punch = on_punch
|
||||
def.on_construct = on_construct
|
||||
def.on_receive_fields = on_receive_fields
|
||||
def.allow_metadata_inventory_move = allow_metadata_inventory_move
|
||||
def.allow_metadata_inventory_put = allow_metadata_inventory_put
|
||||
def.allow_metadata_inventory_take = allow_metadata_inventory_take
|
||||
def.on_metadata_inventory_move = on_metadata_inventory_move
|
||||
def.on_metadata_inventory_put = on_metadata_inventory_put
|
||||
def.on_metadata_inventory_take = on_metadata_inventory_take
|
||||
minetest.register_node(nodename, def)
|
||||
|
||||
-- set node configuration for hooks
|
||||
|
122
os.lua
122
os.lua
@ -10,31 +10,30 @@ 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)
|
||||
node.name = new_node_name
|
||||
if new_node_name then
|
||||
node.name = new_node_name
|
||||
end
|
||||
local fdir = math.floor(node.param2 % 32)
|
||||
node.param2 = fdir + self.theme.node_color * 32
|
||||
print("swap to", dump(node)) --TODO:remove
|
||||
minetest.swap_node(self.pos, node)
|
||||
end
|
||||
|
||||
-- Power on the system and start the launcher
|
||||
function os_class:power_on(new_node_name)
|
||||
if new_node_name then
|
||||
self:swap_node(new_node_name)
|
||||
end
|
||||
self:swap_node(new_node_name)
|
||||
self:set_app() --launcher
|
||||
end
|
||||
|
||||
-- Power on the system / and resume last running app
|
||||
function os_class:resume(new_node_name)
|
||||
if new_node_name then
|
||||
self:swap_node(new_node_name)
|
||||
end
|
||||
self:swap_node(new_node_name)
|
||||
self:set_app(self.appdata.os.current_app)
|
||||
end
|
||||
|
||||
-- Power off the system
|
||||
function os_class:power_off(new_node_name)
|
||||
if new_node_name then
|
||||
self:swap_node(new_node_name)
|
||||
end
|
||||
self:swap_node(new_node_name)
|
||||
self.meta:set_string('formspec', "")
|
||||
self:save()
|
||||
end
|
||||
@ -44,17 +43,6 @@ function os_class:set_infotext(infotext)
|
||||
self.meta:set_string('infotext', infotext)
|
||||
end
|
||||
|
||||
-- Save the data
|
||||
function os_class:save()
|
||||
self.meta:set_string('laptop_appdata', minetest.serialize(self.appdata))
|
||||
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
|
||||
end
|
||||
|
||||
-- Get given or current theme
|
||||
function os_class:get_theme(theme)
|
||||
local theme_sel = theme or self.appdata.os.theme
|
||||
@ -67,6 +55,7 @@ function os_class:set_theme(theme)
|
||||
self.appdata.os.theme = theme
|
||||
self.theme = self:get_theme()
|
||||
self:save()
|
||||
self:swap_node()
|
||||
end
|
||||
end
|
||||
|
||||
@ -124,18 +113,65 @@ function os_class:set_app(appname)
|
||||
end
|
||||
|
||||
-- Handle input processing
|
||||
function os_class:receive_fields(fields, sender)
|
||||
function os_class:pass_to_app(method, reshow, sender, ...)
|
||||
local appname = self.appdata.os.current_app or self.hwdef.custom_launcher or "launcher"
|
||||
local app = self:get_app(appname)
|
||||
app:receive_fields(fields, sender)
|
||||
local ret = app:receive_data(method, reshow, sender, ...)
|
||||
self.appdata.os.last_player = sender:get_player_name()
|
||||
if self.appdata.os.current_app == appname then
|
||||
if self.appdata.os.current_app == appname and reshow then
|
||||
local formspec = app:get_formspec()
|
||||
if formspec ~= false then
|
||||
self.meta:set_string('formspec', formspec)
|
||||
end
|
||||
end
|
||||
self:save()
|
||||
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)
|
||||
@ -146,6 +182,44 @@ function os_class:connect_to_cloud(store_name)
|
||||
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
|
||||
end
|
||||
|
||||
-----------------------------------------------------
|
||||
-- Get Operating system object
|
||||
-----------------------------------------------------
|
||||
|
@ -8,6 +8,7 @@ laptop.themes = {
|
||||
exit_button = "laptop_theme_freedom_exit_button.png",
|
||||
app_button = "laptop_theme_freedom_app_button.png",
|
||||
textcolor = "#000000",
|
||||
node_color = 0,
|
||||
},
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user