storage.lua 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. --[[
  2. Tube Library 2
  3. ==============
  4. Copyright (C) 2017-2020 Joachim Stolberg
  5. LGPLv2.1+
  6. See LICENSE.txt for more information
  7. storage.lua
  8. ]]--
  9. --
  10. -- Data maintenance
  11. --
  12. local MemStore = {}
  13. local storage = minetest.get_mod_storage()
  14. local function update_mod_storage()
  15. local gametime = minetest.get_gametime()
  16. for k,v in pairs(MemStore) do
  17. if v.used then
  18. v.used = false
  19. v.best_before = gametime + (60 * 30) -- 30 min
  20. storage:set_string(k, minetest.serialize(v))
  21. elseif v.best_before < gametime then
  22. storage:set_string(k, minetest.serialize(v))
  23. MemStore[k] = nil -- remove from memory
  24. end
  25. end
  26. -- run every 10 minutes
  27. minetest.after(600, update_mod_storage)
  28. end
  29. minetest.register_on_shutdown(function()
  30. for k,v in pairs(MemStore) do
  31. storage:set_string(k, minetest.serialize(v))
  32. end
  33. end)
  34. minetest.after(600, update_mod_storage)
  35. local function empty_block(block)
  36. local empty = true
  37. local tbl = minetest.deserialize(block)
  38. for k,v in pairs(tbl) do
  39. if k ~= "used" and k ~= "best_before" then
  40. empty = false
  41. end
  42. end
  43. return empty
  44. end
  45. minetest.after(1, function()
  46. local tbl = storage:to_table()
  47. for k,v in pairs(tbl.fields) do
  48. if empty_block(v) then
  49. storage:set_string(k, "")
  50. end
  51. end
  52. end)
  53. --
  54. -- Local helper functions
  55. --
  56. local function new_block(block_key)
  57. local data = storage:get_string(block_key)
  58. if data == nil or data == "" then -- TODO: change for v5
  59. MemStore[block_key] = {}
  60. else
  61. MemStore[block_key] = minetest.deserialize(data)
  62. end
  63. return MemStore[block_key]
  64. end
  65. local function new_node(block, node_key)
  66. block[node_key] = {}
  67. return block[node_key]
  68. end
  69. local function unlock(pos)
  70. local block_key = math.floor((pos.z+32768)/16)*4096*4096 +
  71. math.floor((pos.y+32768)/16)*4096 + math.floor((pos.x+32768)/16)
  72. local node_key = (pos.z%16)*16*16 + (pos.y%16)*16 + (pos.x%16)
  73. local block = MemStore[block_key] or new_block(block_key)
  74. block.used = true
  75. return block, node_key
  76. end
  77. local function keys_to_pos(block_key, node_key)
  78. local f = math.floor
  79. block_key = tonumber(block_key) or 0
  80. node_key = tonumber(node_key) or 0
  81. local x = ((f(block_key % 0x1000) * 0x10) - 32768) + (node_key % 0x10)
  82. block_key, node_key = f(block_key / 0x1000), f(node_key / 0x10)
  83. local y = ((f(block_key % 0x1000) * 0x10) - 32768) + (node_key % 0x10)
  84. block_key, node_key = f(block_key / 0x1000), f(node_key / 0x10)
  85. local z = ((f(block_key % 0x1000) * 0x10) - 32768) + (node_key % 0x10)
  86. return {x = x, y = y, z = z}
  87. end
  88. -------------------------------------------------------------------------------
  89. -- API functions for a node related and high efficient storage table
  90. -- for all kind of node data.
  91. -------------------------------------------------------------------------------
  92. -- To be called when a node is placed
  93. function tubelib2.init_mem(pos)
  94. local block, node_key = unlock(pos)
  95. return new_node(block, node_key)
  96. end
  97. -- To get the node data table
  98. function tubelib2.get_mem(pos)
  99. local block, node_key = unlock(pos)
  100. return block[node_key] or new_node(block, node_key)
  101. end
  102. -- To be called when a node is removed
  103. function tubelib2.del_mem(pos)
  104. local block, node_key = unlock(pos)
  105. block[node_key] = nil
  106. end
  107. -- Read a value, or return the default value if not available
  108. function tubelib2.get_mem_data(pos, key, default)
  109. return tubelib2.get_mem(pos)[key] or default
  110. end
  111. function tubelib2.walk_over_all(clbk, key)
  112. local data = storage:to_table()
  113. for block_key,sblock in pairs(data.fields) do
  114. local block = minetest.deserialize(sblock)
  115. for node_key,mem in pairs(block) do
  116. if mem and node_key ~= "used" and node_key ~= "best_before" then
  117. if key == nil or (type(mem) == "table" and mem[key] ~= nil) then
  118. local pos = keys_to_pos(block_key, node_key)
  119. local node = tubelib2.get_node_lvm(pos)
  120. if key ~= nil then
  121. -- only specified 'key'
  122. clbk(pos, node, {[key] = mem[key]})
  123. else
  124. -- without specified 'key'
  125. clbk(pos, node, mem)
  126. end
  127. end
  128. end
  129. end
  130. end
  131. end