block_devices.lua 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. local mod_storage = minetest.get_mod_storage()
  2. local bdev = {}
  3. -- Check hardware capabilities { "hdd", "floppy", "usb", "net", "liveboot" }
  4. function bdev:is_hw_capability(hw_cap)
  5. for i, cap in ipairs(self.os.hwdef.hw_capabilities) do
  6. if cap == hw_cap or cap == hw_cap:sub(18, -1) then --"laptop_removable_*"then
  7. return cap
  8. end
  9. end
  10. return false
  11. end
  12. -- Get RAM
  13. function bdev:get_ram_disk()
  14. if not self.ram_disk then
  15. self.ram_disk = minetest.deserialize(self.os.meta:get_string('laptop_ram')) or {}
  16. end
  17. return self.ram_disk
  18. end
  19. function bdev:free_ram_disk()
  20. self.ram_disk = {}
  21. self:sync()
  22. end
  23. -- Get HDD if exists
  24. function bdev:get_hard_disk()
  25. if self.hard_disk == nil then
  26. if self:is_hw_capability('hdd') then
  27. self.hard_disk = minetest.deserialize(self.os.meta:get_string('laptop_appdata')) or {}
  28. else
  29. self.hard_disk = false
  30. end
  31. end
  32. return self.hard_disk
  33. end
  34. -- Get Removable disk if exists
  35. function bdev:get_removable_disk(removable_type)
  36. if self.removable_disk == nil then
  37. local data = { bdev = self }
  38. data.inv = self.os.meta:get_inventory()
  39. data.inv:set_size("main", 1) -- 1 disk supported
  40. function data:reload(stack)
  41. -- self.inv unchanged
  42. -- self.rtype unchanged (assumption
  43. stack = stack or self.inv:get_stack("main", 1)
  44. if stack then
  45. local def = stack:get_definition()
  46. if def and def.name ~= "" then
  47. self.stack = stack
  48. self.def = def
  49. self.meta = stack:get_meta()
  50. self.os_format = self.meta:get_string("os_format")
  51. if self.os_format == "" then
  52. self.os_format = "none"
  53. end
  54. self.label = self.meta:get_string("description")
  55. if self.label == "" then
  56. self.label = self.def.description
  57. end
  58. for group, _ in pairs(self.def.groups) do
  59. local rtype_chk = self.bdev:is_hw_capability(group)
  60. if not removable_type or removable_type == rtype_chk then
  61. self.rtype = rtype_chk
  62. break
  63. end
  64. end
  65. self.storage = minetest.deserialize(self.meta:get_string("os_storage")) or {}
  66. end
  67. end
  68. end
  69. function data:eject()
  70. if not self.stack then
  71. return false
  72. end
  73. local p = self.bdev.os.pos
  74. local drop_pos = { x=p.x+math.random()*2-1, y=p.y,z=p.z+math.random()*2-1 }
  75. minetest.item_drop(self.stack, nil, drop_pos)
  76. self.stack = nil
  77. return true
  78. end
  79. function data:format_disk(ftype, label)
  80. self.stack = ItemStack(self.def.name)
  81. self.meta = self.stack:get_meta()
  82. self.meta:set_string("os_format", ftype or "")
  83. self.os_format = ftype
  84. self.label = label or ""
  85. end
  86. data:reload()
  87. self.removable_disk = data
  88. end
  89. return self.removable_disk
  90. end
  91. -- Connect to cloud
  92. function bdev:get_cloud_disk(store_name)
  93. if self.cloud_disk == nil or (self.cloud_disk ~= false and not self.cloud_disk[store_name]) then
  94. if self:is_hw_capability('net') then
  95. self.cloud_disk = self.cloud_disk or {}
  96. self.cloud_disk[store_name] = minetest.deserialize(mod_storage:get_string(store_name)) or {}
  97. else
  98. self.cloud_disk = false
  99. return false
  100. end
  101. end
  102. return self.cloud_disk[store_name]
  103. end
  104. -- Get device to boot
  105. function bdev:get_boot_disk()
  106. if self:is_hw_capability('liveboot') then
  107. local drive = self:get_removable_disk()
  108. if drive.stack and drive.os_format == 'boot' then
  109. return 'removable'
  110. end
  111. end
  112. return 'hdd'
  113. end
  114. -- Get app related object from storage "disk_type"
  115. function bdev:get_app_storage(disk_type, store_name)
  116. if disk_type == 'ram' then
  117. local store = self:get_ram_disk()
  118. store[store_name] = store[store_name] or {}
  119. return store[store_name]
  120. elseif disk_type == 'hdd' then
  121. local store = self:get_hard_disk()
  122. if store then
  123. store[store_name] = store[store_name] or {}
  124. return store[store_name]
  125. else
  126. return nil
  127. end
  128. elseif disk_type == 'removable' then
  129. local store = self:get_removable_disk()
  130. if store.stack and (store.os_format == 'data' or store.os_format == 'boot') then
  131. store.storage[store_name] = store.storage[store_name] or {}
  132. return store.storage[store_name]
  133. else
  134. return nil
  135. end
  136. elseif disk_type == 'system' then
  137. local runtime = self:get_app_storage("ram", "os")
  138. runtime.booted_from = runtime.booted_from or self:get_boot_disk()
  139. return self:get_app_storage(runtime.booted_from, store_name)
  140. elseif disk_type == 'cloud' then
  141. return self:get_cloud_disk(store_name) or nil
  142. end
  143. end
  144. -- Save all data if used
  145. function bdev:sync()
  146. -- save RAM
  147. self.os.meta:set_string('laptop_ram', minetest.serialize(self.ram_disk))
  148. self.os.meta:mark_as_private('laptop_ram')
  149. -- save HDD
  150. if self.hard_disk then
  151. self.os.meta:set_string('laptop_appdata', minetest.serialize(self.hard_disk))
  152. self.os.meta:mark_as_private('laptop_appdata')
  153. end
  154. -- save removable
  155. if self.removable_disk then
  156. if self.removable_disk.stack then
  157. if self.removable_disk.def and self.removable_disk.label ~= self.removable_disk.def.description then
  158. self.removable_disk.meta:set_string("description", self.removable_disk.label)
  159. end
  160. if self.removable_disk.storage and next(self.removable_disk.storage) then
  161. self.removable_disk.meta:set_string("os_storage", minetest.serialize(self.removable_disk.storage))
  162. end
  163. end
  164. self.removable_disk.inv:set_stack("main", 1, self.removable_disk.stack)
  165. end
  166. end
  167. -- Save all data if used
  168. function bdev:sync_cloud()
  169. -- Modmeta (Cloud)
  170. if self.cloud_disk then
  171. for store, value in pairs(self.cloud_disk) do
  172. mod_storage:set_string(store, minetest.serialize(value))
  173. end
  174. end
  175. end
  176. -- Get handler
  177. function laptop.get_bdev_handler(mtos)
  178. local bdevobj = {}
  179. for k,v in pairs(bdev) do
  180. bdevobj[k] = v
  181. end
  182. bdevobj.os = mtos
  183. return bdevobj
  184. end